© Vaskaran Sarcar 2019
Vaskaran SarcarJava Design Patternshttps://doi.org/10.1007/978-1-4842-4078-6_14

14. Observer Pattern

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

This chapter covers the observer pattern.

GoF Definition

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Concept

In this pattern, there are many observers (objects) that are observing a particular subject (also an object). Observers register themselves to a subject to get a notification when there is a change made inside that subject. When they lose interest of the subject, they simply unregister from the subject. It is also referred to as the publish-subscribe pattern . The whole idea can be summarized as follows: Using this pattern, an object (subject) can send notifications to multiple observers (a set of objects) at the same time.

You can visualize the scenarios in the following diagrams.

Step 1. Observers are requesting a subject to get notifications (see Figure 14-1).
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig1_HTML.jpg
Figure 14-1

Step 1

Step 2. The subject grants the requests and the connection is established (see Figure 14-2).
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig2_HTML.jpg
Figure 14-2

Step 2

Step 3. The subject sends notifications to the registered users (in case a typical event occurs in the subject and it wants to notify others) (see Figure 14-3).
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig3_HTML.jpg
Figure 14-3

Step 3

Step 4 (optional). Observer2 does not want to get further notification, so it unregisters itself (see Figure 14-4).
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig4_HTML.jpg
Figure 14-4

Step 4

Step 5. Now onward, only Observer1 and Observer3 get notifications from the subject (see Figure 14-5).
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig5_HTML.jpg
Figure 14-5

Step 5

Real-World Example

Think about a celebrity who has many followers on social media. Each of these followers wants all the latest updates from their favorite celebrity. So, they follow the celebrity until their interest wanes. When they lose interest, they simply do not follow that celebrity any longer. You can think each of these fans or followers as an observer and the celebrity as a subject.

Computer-World Example

In the world of computer science, consider a simple UI-based example. Let’s assume that this UI is connected to a database. A user can execute a query through that UI, and after searching the database, the result is returned in the UI. Here you segregate the UI from the database in such a way that if a change occurs in the database, the UI is notified, and it updates its display according to the change.

To simplify this scenario, assume that you are the person responsible for maintaining a particular database in your organization. Whenever there is a change made inside the database, you want a notification so that you can take action if necessary.

Note

In general, you see the presence of this pattern in event-driven software. Modern languages like C#, Java, and so forth have built-in support for handling events following this pattern. Those constructs make your life easy.

In Java, you can see the use of event listeners. These listeners are observers only. In Java, you have a ready-made class called Observable, which can have multiple observers. These observers need to implement the Observer interface. The Observer interface has an “update” method: void update(Observable o,Object arg). This method is invoked whenever a change occurs in the observed object. Your application needs to call the Observable object’s notifyObservers method to notify about the change to the observers. The addObserver(Observer o) and deleteObserver(Observer o) methods add or and delete an observer, similar to the register and unregister methods discussed earlier. You can learn more from https://​docs.​oracle.​com/​javase/​8/​docs/​api/​java/​util/​Observer.​html and https://​docs.​oracle.​com/​javase/​8/​docs/​api/​index.​html?​java/​util/​Observable.​html.

If you are familiar with the .NET Framework, you see that in C#, you have the generic System.IObservable<T> and System.IObserver<T> interfaces, where the generic type parameter provides notifications.

Illustration

Let’s consider the following example and go through the post analysis of the output. I have created three observers and one subject. The subject maintains a list for all its registered users. Our observers want to receive notification when a flag value changes in the subject. In the output, you discover that the observers are getting the notifications when flag values are changed to 5, 50, and 100, respectively. But one of them did not receive any notification when the flag value changed to 50, because at that moment, he was not a registered user in subject. But in the end, he is getting notifications because he registered himself again.

In this implementation, the register(), unregister(), and notifyRegisteredUsers() methods have their typical meanings. The register() method registers an observer in the subject’s notification list, the unregister() method removes an observer from the subject’s notification list, and notifyRegisteredUsers() notifies all the registered users when a typical event occurs in the subject.

Class Diagram

Figure 14-6 shows the class diagram.
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig6_HTML.jpg
Figure 14-6

Class diagram

Package Explorer View

Figure 14-7 shows high-level structure of the program.
../images/395506_2_En_14_Chapter/395506_2_En_14_Fig7_HTML.jpg
Figure 14-7

Package Explorer view

Implementation

Here is the implementation.
package jdp2e.observer.demo;
import java.util.*;
interface Observer
{
    void update(int updatedValue);
}
class ObserverType1 implements Observer
{
    String nameOfObserver;
    public ObserverType1(String name)
    {
        this.nameOfObserver = name;
    }
    @Override
    public void update(int updatedValue)
    {
        System.out.println( nameOfObserver+" has received an alert: Updated myValue in Subject is: "+ updatedValue);
    }
}
class ObserverType2 implements Observer
{
    String nameOfObserver;
    public ObserverType2(String name)
    {
        this.nameOfObserver = name;
    }
    @Override
    public void update(int updatedValue)
    {
        System.out.println( nameOfObserver+" has received an alert: The current value of myValue in Subject is: "+ updatedValue);
    }
}
interface SubjectInterface
{
    void register(Observer anObserver);
    void unregister(Observer anObserver);
    void notifyRegisteredUsers(int notifiedValue);
}
class Subject implements SubjectInterface
{
    private int flag;
    public int getFlag()
    {
        return flag;
    }
    public void setFlag(int flag)
    {
        this.flag = flag;
        //Flag value changed. So notify registered users/observers.
        notifyRegisteredUsers(flag);
    }
    List<Observer> observerList = new ArrayList<Observer>();
    @Override
    public void register(Observer anObserver) {
        observerList.add(anObserver);
    }
    @Override
    public void unregister(Observer anObserver) {
        observerList.remove(anObserver);
    }
    @Override
    public void notifyRegisteredUsers(int updatedValue)
    {
        for (Observer observer : observerList)
            observer.update(updatedValue);
    }
}
public class ObserverPatternExample {
    public static void main(String[] args) {
        System.out.println(" ***Observer Pattern Demo*** ");
        //We have 3 observers- 2 of them are ObserverType1, 1 of them is of //ObserverType2
        Observer myObserver1 = new ObserverType1("Roy");
        Observer myObserver2 = new ObserverType1("Kevin");
        Observer myObserver3 = new ObserverType2("Bose");
        Subject subject = new Subject();
        //Registering the observers-Roy,Kevin,Bose
        subject.register(myObserver1);
        subject.register(myObserver2);
        subject.register(myObserver3);
        System.out.println(" Setting Flag = 5 ");
        subject.setFlag(5);
        //Unregistering an observer(Roy))
        subject.unregister(myObserver1);
        //No notification this time Roy. Since it is unregistered.
        System.out.println(" Setting Flag = 50 ");
        subject.setFlag(50);
        //Roy is registering himself again
        subject.register(myObserver1);
        System.out.println(" Setting Flag = 100 ");
        subject.setFlag(100);
    }
}

Output

Here is the output.
***Observer Pattern Demo***
 Setting Flag = 5
Roy has received an alert: Updated myValue in Subject is: 5
Kevin has received an alert: Updated myValue in Subject is: 5
Bose has received an alert: The current value of myValue in Subject is: 5
 Setting Flag = 50
Kevin has received an alert: Updated myValue in Subject is: 50
Bose has received an alert: The current value of myValue in Subject is: 50
 Setting Flag = 100
Kevin has received an alert: Updated myValue in Subject is: 100
Bose has received an alert: The current value of myValue in Subject is: 100
Roy has received an alert: Updated myValue in Subject is: 100

Analysis

Initially, all three observers—Roy, Kevin and Bose—registered for notifications from the subject. So, in the initial phase, all of them received notifications. At some point, Roy became disinterested in notifications, so he unregistered himself. So, from this time onward, only Kevin and Bose received notifications (notice when I set the flag value to 50). But Roy has changed his mind and he re-registered himself to get notifications from the subject. So, in the final case, all of them received notifications from the subject.

Q&A Session

  1. 1.

    If I have only one observer, then I may not need to set up the interface. Is this correct?

    Yes. But if you want to follow the pure object-oriented programming guidelines, programming to an interface/abstract class is always considered a better practice. So, you should prefer interfaces (or abstract classes) over concrete classes. Also, usually, you have multiple observers, and you want them to implement the methods in a systematic manner that follows the contract. You get benefit from this kind of design.

     
  2. 2.

    Can you have different types of observers in the same application?

    Yes. This is why I have played with three observers from two different classes. But you should not feel that for each observer; you need to create a different class.

    Consider a real-world scenario. When a company releases or updates new software, the company business partners and the customers who purchased the software get notifications. In this case, the business partners and the customers are two different types of observers.

     
  3. 3.

    Can I add or remove observers at runtime?

    Yes. At the beginning our program, Roy registered to get notifications; then he unregistered and later reregistered.

     
  4. 4.

    It appears that there are similarities between the observer pattern and the chain of responsibility pattern. Is this correct?

    In an observer pattern, all registered users get notifications at the same time, but in a chain of responsibility pattern, objects in the chain are notified one by one, and this process continues until the object fully handles the notification. Figure 14-8 and Figure 14-9 summarize the differences.
    ../images/395506_2_En_14_Chapter/395506_2_En_14_Fig8_HTML.jpg
    Figure 14-8

    The basic workflow of an observer pattern

    ../images/395506_2_En_14_Chapter/395506_2_En_14_Fig9_HTML.jpg
    Figure 14-9

    The basic workflow of a chain of responsibility pattern

     
  5. 5.

    This model supports one-to-many relationships. Is this correct?

    Yes. Since a subject can send notifications to multiple observers, this kind of dependency is clearly depicting a one-to-many relationship.

     
  6. 6.

    If you already have these ready-made constructs, why are you writing your own code?

    Changing the ready-made constructs to your preference is not always easy. In many cases, you cannot change the built-in functionalities at all. When you try to implement the concept yourself, you may have a better understanding of how to use those ready-made constructs.

    Consider some typical scenarios.
    • In Java, Observable is a concrete class. It does not implement an interface. So, you can’t create your own implementation that works with Java’s built-in Observer API.

    • Java does not allow multiple inheritance. So, when you have to extend the Observable class, you have to keep in mind the restriction. This may limit the reuse potential.

    • The signature of the setChanged method in an Observable is as follows: protected void setChanged(). That means to use it, you need to subclass Observable class. This violates one of the key design principles, which basically says to prefer composition over inheritance.

     
  7. 7.
    What are the key benefits of the observer pattern?
    • The subject and its registered users(observers) are making a loosely coupled system. They do not need to know each other explicitly.

    • No modification is required in subjects when you add or remove an observer from its notification lists.

    • Also, you can independently add or remove observers at any time.

     
  8. 8.
    What are the key challenges associated with an observer pattern?
    • Undoubtedly, memory leak is the greatest concern when you deal with any event-based mechanism. An automatic garbage collector may not always help you in this context. You can consider such a case where the deregister/unregister operations are not performed properly.

    • The order of notification is not dependable.

    • Java’s built-in support for the observer pattern has some key restrictions, which I discussed earlier. (Revisit the answer to question 6 .) One of them forces you to prefer inheritance over composition, so it clearly violates one of the key design principles that prefers the opposite.

     
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset