Observer Design Pattern

Design Pattern Tutorial Series

Observer Design Pattern in Java - 5-Step Guide

The Observer Pattern is a frequently used and very practical design pattern. Mastering this pattern will probably be a great help for any developer. As a behavioral pattern, the observer pattern provides one object with a loosely couple method of informing multiple objects of property changes.

Table of Contents

observer-design-pattern-overview-INTEGU

Step 1 - The Objective

The general idea of the observer pattern is to provide one object (the Subject) with the capabilities of informing multiple different objects (the Observers) of property changes.

Building on the example from the tutorial video, we can imagine that we have a journalist as the subject. A journalist writes articles and every time they finish one, they publish it through a variety of distribution channels. These distribution channels could range from anything like television news, newspapers, and online publishers. We recognize each of these distribution channels as observers.

At the point of delivering the new article to the distribution channels, the journalist learns that the different channels do not want the same content from the article. This naturally frustrates the journalist. Their job is writing the article, and not to manage what content each individual channel wants.

Let’s try and take a look at how this problem is being solved right now and how the observer pattern can ease the burden on the journalist.

observer-design-pattern-objective-INTEGU

Step 2 - Subject's Responsibility

As we saw above, the journalist is currently managing how all the content, including the headline, text, picture, and summary, is being distributed between the channels.

To convert this scenario into code, imagine a Journalist-class, which have an instance of the TelevisionNews, Newspaper, and OnlinePublisher. For the journalist to provide each of the observers with the desired content, the journalist must call each of the observers’ publish()-method individually and provide their desired content as arguments. Sounds like a lot of responsibilities for a journalist.

Additionally, with this code structure, it will not be possible for the journalist to change observers at runtime. Since the journalist does not have a common method of publishing their article it will not be possible to make a simple way of adding new observers. They are therefore restricted to selecting their observers at compile time. Something has to change, so let’s see what the observer pattern can do for us.

class Journalist {
    TelevisionNews televisionNews;
    Newspaper newspaper;
    OnlinePublisher onlinePublisher;
    public Journalist() {
        televisionNews = new TelevisionNews();
        newspaper = new Newspaper();
        onlinePublisher = new OnlinePublisher();
    }
    void publish(String title, String summary, String image, String text){
        televisionNews.publish(headline, picture);
        newspaper.publish(headline, text, picture, summary);
        onlinePublisher.publish(headline, picture, summary);
    }
}
observer-design-pattern-disadvantage-INTEGU

Step 3 - Concept Of The Observer Pattern

Focusing on the two issues we experience in the scenario above. We want to move the responsibility of getting the correct content, from the subject to the observers. Secondly, we want to be able to add and remove observers at runtime. Perhaps some of the distribution channels does not present the content appropriately or new channels occur?

The way that both issues are solved is by implementing a layer of abstraction for both subject and observers. This way both sides know what to expect from each other. To see how this works, we will have to dive into the class diagram.

observer-design-pattern-advantage-INTEGU

Step 4 - Class Diagram (UML)

In the class diagram, we can see that both a subject- and observer interface have been created and implemented by our concrete classes. The subject interface states three methods, which the Journalist-class has to implement: registerObserver(), removeObserver(), and notifyObserver(). Through these three methods, we gain a structure of how to manage the number of observers. At the same time, we also gain a method for telling all observers when a new article has been published.

Since the subject knows that the observers have to implement the Observer interface, it can rely on them having the update()-method. The update method takes a Subject-object as its argument, which allows it to utilize its getter-methods after casting it. This will become clearer in the code snippets.

Since all observers only take a Subject-object as its argument for the update method, the Subject has hereby also gained a way of handling all observers the same way. Instead of the subject having to remember the observers’ inputs, the observers can instead utilize the getters on the Subject-object to get exactly the information they require.

observer-design-pattern-class-diagram-INTEGU

Step 5 - Code (Java)

Given that code is sometimes difficult to learn through concepts and theory, I provide the code for the example in both video and blog form. 

Hopefully, this will be sufficient for you to learn to identify and implement the Observer Pattern in your future endeavors as a software developer.

Observer

interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObserver();
}
class Journalist implements Subject {
    private ArrayList observers = new ArrayList<>();
    private String title, summary, image, text;
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    @Override
    public void notifyObserver() {
        observers.forEach(observer -> observer.update(this));
    }
    public void publish(String title, String summary, String image, String text) {
        this.title = title;
        this.summary = summary;
        this.image = image;
        this.text = text;
        notifyObserver();
    }
    public String getTitle() {
        return title;
    }
    public String getSummary() {
        return summary;
    }
    public String getImage() {
        return image;
    }
    public String getText() {
        return text;
    }
}

Subject

interface Observer {
    void update(Subject subject);
}
class Newspaper implements Observer {
    @Override
    public void update(Subject subject) {
        if (subject instanceof Journalist) {
            String title = ((Journalist) subject).getTitle();
            String summary = ((Journalist) subject).getSummary();
            String image = ((Journalist) subject).getImage();
            String text = ((Journalist) subject).getText();
        }
    }
}

How to use the Observer Pattern

    public static void main(String [] args) {
        Journalist journalist = new Journalist();
        journalist.registerObserver(new Newspaper());
        journalist.registerObserver(new TVNews());
        journalist.registerObserver(new OnlinePublishing());
        journalist.publish("Birds going extinct", 
                "Summary: Research from the university of ...", 
                "Image of Birds", 
                "The number of birds are going down ...");
    }

Recommended Reading

Article

  • Theoretical walkthrough – Source Making – Blog
  • Practical walkthrough – Tutorialspoint – Blog
  • Practical walkthrough – Springframework Guru – Blog

Books

Video Tutorial 

 

  • Theoretical  (based on “Head-First: Design Patterns”) – Christopher Okhravi – YouTube
  • Practical – Derek Banas – YouTube

Tools

  • Camtasia – Used for illustrations and video – Camtasia

About

Hi, I'm the Author

My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT. 

I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities. 

The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.

If you like the idea of that, I would encourage you to sign up for the newsletter.

Cheers! 🍺

Didn't Find What You Were Looking For?

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Scroll to Top