The Observer Pattern uses two abstract classes or interfaces:
Observed (also called Subject).
The Observer Pattern is used when there is a "one to many relationship between objects" such as if one object is modified,
its depenedent objects are to be notified automatically. The diagram below illustrates the structure:
Structure of the Observer Pattern
Each Observer object possesses an update() method which is invoked by the Observed object when the Observed object changes.
The Observer pattern is also responsible for telling the Observed object that it should notify the Observer object when it changes.
Use the Observer pattern in any of the following situations:
When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
When a change to one object requires changing others, and you don't know how many objects need to be changed.
When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.
Observer Pattern as Alternative to MVC
You might think of the Observer pattern as an alternative to the MVC Pattern. At the root of the Observer Pattern are Subject and Observer interfaces.
The Subject holds a given state and
the observers subscribe to the subject to be informed of the current state.
You can think of it as a blog with many subscribers, where one set of information is routinely updated for a variety of users who subscribe or regularly read the blog. Each time the blog is updated (its state changes) and all of the subscribers are informed.
Figure 14-1 shows the Observer class diagram.
One of the more interesting and possibly perplexing features of this pattern is the methods of the Subject. While the italicized title "Subject" title indicates an interface (an abstract class in this case), abstract methods are italicized as well. However, as you can see in Figure 6-6, none of the methods are italicized. It is clear
which methods Subject generates, and
the Notify() method even has pseudocode to help out.
You will find several different implementations of the Observer pattern.
The Observed object must keep a list of the objects observing it. It must provide an interface for adding objects to and removing objects from that list. Finally, it contains the necessary methods that result in changes to its state. Every time the Observed state of the object changes, it cycles through the list, notifying each Observer in turn of the change.
The Observer interface declares the update method that the Observed object will invoke. This method does whatever the class wants to do as a result of the notification.
Observer interface in java.util
The java.util package actually has an interface (or abstract class) called Observer and a class called Observable. However, neither is much used, even though the delegation event model used in Java 1.1 makes heavy use of the Observer pattern. The reason is that java.util.Observable is a class rather than an interface. To use these two predefined bits of code your Observed object must extend Observable. In Java's single inheritance hierarchy, this is a huge impediment. This is one case where the abstract nature of the main classes is essential.
public interface Observer:
A class can implement the Observer interface when it wants to be informed of changes in observable objects. After applying the Observer pattern, different observers can be added dynamically without requiring any changes to the Subject class.
Similarly, observers remain unaffected when the state change logic of the subject changes.
The Observer pattern is useful for designing a consistent communication model between a set of dependent objects and an object that they are dependent on. This allows the dependent objects to have their state synchronized with the object that they are dependent on. The set of dependent objects are referred to as observers and the object that they are dependent on is referred to as the subject. In order to accomplish this, the Observer pattern suggests a publisher-subscriber model leading to a clear boundary between
the set of Observer objects and
the Subject object.
MVC within the context of Observer
In the (MVC) model-view-controller architecture the model is the real thing, and the views approximate it. Think instead of a model that poses for a painting. The model is real, and different artists can observe the same model and draw different views. Here is what happens when a user types text into one of the windows:
The controller tells the model to insert the text that the user typed.
The model notifies all views of a change in the model.
All views repaint themselves.
During painting, each view asks the model for the current text.
This architecture minimizes the coupling between the 1) model, 2) views, and 3) controllers. The model knows nothing about the views, except that they need to be notified of all changes. The views know nothing of the controllers and it is easy to add more views to a model. It is also easy to change the controller of a view, for example to facilitate voice input. Let us have a closer look at the notification mechanism.
The model knows about a number of observers, namely, the views.
An observer is an object that is interested in state changes of the model.
The model knows nothing in detail about the observers except that it should notify them whenever the model data changes.
Observer Pattern as an alternative to MVC
The Observer Pattern and the Model-View-Controller (MVC) Pattern are both design patterns used in software engineering to separate concerns and make systems more maintainable, extensible, and testable. Though they are often used together, the Observer Pattern can serve as an alternative to MVC in some cases, depending on the specific requirements of the application. Here's how:
Subject: The object holding the data or the state.
Observer: The object that wishes to be informed when the state of the Subject changes.
The Subject maintains a list of Observers and notifies them of state changes.
Model: Manages the data, logic, and rules of the application.
View: Displays the data, receives user input.
Controller: Interprets user actions and updates the Model and/or View.
How the Observer Pattern Can Serve as an Alternative to MVC:
Simpler Applications: For simple applications where the logic between the Model and View isn't complex, the Observer Pattern might be sufficient for updating the View whenever the Model (Subject) changes, without needing a Controller.
Direct Updates: In MVC, the Controller typically manipulates the Model, which then updates the View. With the Observer Pattern, the Model can directly notify the View (Observer) to update, potentially simplifying the update flow.
Decoupling: Just like MVC, the Observer Pattern provides a level of decoupling between the data (Subject) and the presentation layer (Observer). This is good for maintainability and testing.
Dynamic Subscription: Observers can dynamically subscribe or unsubscribe to Subjects, providing flexibility in how views are updated that can sometimes be more fine-grained than the traditional MVC approach.
Less Boilerplate: In some implementations, MVC can require a lot of boilerplate code to wire up Controllers, Models, and Views. An Observer-based approach could be simpler and faster for prototyping or smaller projects.
State Management: Some modern front-end frameworks leverage the Observer Pattern or similar paradigms (like React’s state and props system) for state management, making it easier to manage complex state dependencies without a separate Controller.
Modularity: The Observer Pattern encourages modular design, allowing for easy extensions and modifications without affecting other parts of the system.
Multiple Views: Just like MVC, multiple Views can observe a single Model. This makes it easy to create alternative interfaces or components that reflect the same underlying data.
However, it’s worth mentioning that MVC and the Observer Pattern can also co-exist in a complementary manner.
For instance, the Model in an MVC architecture could serve as the Subject in an Observer Pattern, with multiple Views acting as Observers.
In summary, while the Observer Pattern can be used as an alternative to MVC for some types of applications, the best choice will depend on the specific needs and complexities of the project.