In this article, we will do an in-depth exploration of Observer Design Pattern in Java. So, let’s get started.
What is Observer Design Pattern in Java ?
Observer design pattern in Java is useful when you are interested in the state of an object and want to get notified whenever there is any change. In observer pattern, the object that watch on the state of another object are called Observer and the object that is being watched is called Subject.
Java provides inbuilt platform for implementing Observer pattern through java.util.Observable class and java.util.Observer interface.
Java Message Service (JMS) uses Observer pattern along with Mediator pattern to allow applications to subscribe and publish data to other applications.
UML Diagram
Example: Observer Design Pattern in Java
In the below example, we will implement a Blogger-Subscriber model.
Class Diagram of Our Example
Java Code
// Subject Interface
package com.design.observer;
public interface Subject {
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
public String getUpdate();
}
// Blog Class
package com.design.observer;
import java.util.ArrayList;
import java.util.List;
public class Blog implements Subject {
private String newArticleUrl = null;
private List observers = new ArrayList < > ();
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer: observers) {
observer.update();
}
}
@Override
public String getUpdate() {
if (newArticleUrl == null) {
return "No new article published";
}
return newArticleUrl;
}
public void setNewArticleUrl(String newArticleUrl) {
this.newArticleUrl = newArticleUrl;
}
public void postNewArticle(String newArticleUrl) {
System.out.println("Posting new Artcle " + newArticleUrl);
setNewArticleUrl(newArticleUrl);
notifyObservers();
}
}
// Observer Interface
package com.design.observer;
public interface Observer {
public void update();
}
// BlogSubscriber Class
package com.design.observer;
public class BlogSubscriber implements Observer {
private Subject blog;
public BlogSubscriber(Subject blog) {
this.blog = blog;
blog.addObserver(this);
}
@Override
public void update() {
String artculeUrl = blog.getUpdate();
System.out.println("Got update about the new article " + artculeUrl);
}
}
// ObserverDemo Class
package com.design.observer;
public class ObserverDemo {
public static void main(String[] args) {
Blog blog = new Blog();
new BlogSubscriber(blog);
new BlogSubscriber(blog);
blog.postNewArticle("http://www.test.blog/JavaGyan");
}
}
// Output
Posting new Artcle http: //www.test.blog/JavaGyan
Got update about the new article http: //www.test.blog/JavaGyan
Got update about the new article http: //www.test.blog/JavaGyan
Use-Cases for Observer Design Pattern in Java
- Event Handling: Implementing event-driven systems where objects need to notify others about changes or events, such as GUI components reacting to user interactions.
- UI Components: Keeping user interfaces synchronized with underlying data changes, ensuring that changes in one component are reflected in others.
- Stock Market Updates: Broadcasting real-time updates to various stock market observers whenever stock prices change.
- Messaging Systems: Notifying subscribers about new messages or events in messaging systems.
- Notification Services: Sending notifications to multiple subscribers when certain conditions are met.
- Weather Updates: Broadcasting weather changes to multiple display elements in a weather monitoring application.
- Traffic Monitoring: Notifying different systems about traffic updates or road closures in a traffic monitoring application.
Pros of Observer Design Pattern in Java
- Loose Coupling: The subject (observable) and observers are loosely coupled, allowing them to interact without direct dependencies.
- Dynamic Update: Observers can be added or removed dynamically without affecting the subject’s core functionality.
- Reusability: Observers can be reused across different subjects, enhancing code modularity.
- Decoupling: The observer pattern decouples the sender and receiver of updates, promoting cleaner and more maintainable code.
- Maintainability: Changes to the subject don’t impact observers, and vice versa, improving code maintainability.
- Scalability: It’s easy to scale up the number of observers or subjects in the system without major code changes.
Cons of Observer Design Pattern in Java
- Order of Execution: The order in which observers are notified might be important, but the pattern doesn’t explicitly control it.
- Complexity: Implementing the observer pattern can increase code complexity, especially in cases with many observers and subjects.
- Memory Leak: If observers aren’t properly removed, they can lead to memory leaks as they hold references to the subject.
Best Practices for Observer Design Pattern in Java
- Clear Contract: Define a clear contract/interface for both subjects and observers to ensure a consistent interaction.
- Efficient Updates: Implement intelligent update mechanisms to avoid unnecessary updates to observers.
- Unregister Mechanism: Provide a way for observers to unregister themselves to prevent memory leaks.
- Use Java Libraries: Utilize built-in Java libraries like
java.util.Observable
andjava.util.Observer
interfaces. - Avoid Overhead: Balance the number of observers to avoid unnecessary overhead in notifying and managing observers.
- Documentation: Clearly document the roles and responsibilities of subjects and observers to aid understanding.
- Testability: Unit test subjects and observers separately to ensure their individual functionality.
Conclusion: Observer Design Pattern in Java
This article provided a comprehensive exploration of the Observer Design Pattern in Java, shedding light on its purpose, implementation, and real-world applications. The Observer pattern proves invaluable when you require objects to react to state changes in other objects. With observers being dynamically attached and detached, this pattern promotes loose coupling between subjects and observers, enhancing code reusability and maintainability.
Through the example of a Blogger-Subscriber model, we illustrated the implementation of the Observer pattern in Java. Moreover, we discussed the practical advantages of this pattern, such as its flexibility, maintainability, and scalability. However, it’s essential to be mindful of potential complexities and memory leaks when implementing this pattern, as well as to adhere to best practices to ensure efficient and organized code.
By understanding the Observer Design Pattern, developers can design systems that seamlessly react to changes and events while maintaining a well-structured and modular codebase.
Must Read Design Pattern Articles: