DEV Community

Sota
Sota

Posted on • Edited on

Observer Pattern

What is Observer Pattern?

Observer pattern is a behavioral pattern that defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

The object changes its state is called Subject, and its dependents are called Observers.

When to use it?

You can use Observer pattern when you need one-to-many dependency between objects, the one will change its state and the many dependents need to keep track of those changes.

Problem

Let's say you are a big fan of NIKE, a famous shoes company. You want to get a new released product as much as possible, so everyday you visit company's website and check if there is new item.
What if the same thing happens in our application? A object needs to continuously check to get new information about other object's state by keeping executing something like getState() method once in a minute or more frequently. However, obviously it is very inefficient since most of the time, getState() returns the same values.

Image description

Solution

Let's assume we use SNS like X(Twitter) or Instagram, companies and people have their own account, and people can follow their favorite company so that people receive notification when the company post about new item or sale item. In this situation, Observer pattern is applicable.

Image description

  1. ICompany (Subject Interface)
    Provides interface for concrete company. It declares methods to register, deregister and notify account.

  2. Company (Subject)
    When setSaleItem method is called (the state is changed), we call setItemChanged method. Then, setItemChanged method calls notifyAccount method. In this way, subject class notifies to observers whenever subject's state changes.
    setSaleItem (state change) -> setItemChanged -> notifyAccount
    notifyAccount method in Company class iterates each follower and call update method with its own Company object such as follower.update(this)

  3. IAccount (Observer Interface)
    Provides interface for observers. This interface has one method declaration update() to define observer's behavior when subject's state changes.

  4. Account (Observer)
    Represents an account. Each account can follow/unfollow company's account. Followers can only receive notification.

Structure

Image description

Implementation in Java

public interface ICompany {

    void registerAccount(IAccount account);

    void removeAccount(IAccount account);

    void notifyAccounts();
}
Enter fullscreen mode Exit fullscreen mode
public class Company implements ICompany {

    private List<IAccount> followers;

    private String name;

    private String saleItem;

    public Company(String name) {
        followers = new ArrayList<>();
        this.name = name;
    }

    @Override
    public void registerAccount(IAccount account) {
        this.followers.add(account);
    }

    @Override
    public void removeAccount(IAccount account) {
        this.followers.remove(account);
    }

    @Override
    public void notifyAccounts() {
        for (IAccount follower : followers) {
            follower.update(this);
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSaleItem() {
        return saleItem;
    }

    public void setSaleItem(String saleItem) {
        this.saleItem = saleItem;
        saleItemChanged();
    }

    public void saleItemChanged() {
        notifyAccounts();
    }
}
Enter fullscreen mode Exit fullscreen mode
public interface IAccount {

    void update(Company company);
}
Enter fullscreen mode Exit fullscreen mode
public class Account implements IAccount {

    private String name;

    public Account(String name) {
        this.name = name;
    }

    @Override
    public void update(Company company) {
        System.out.println(this.name + " receives a new message from " + company.getName());
        System.out.println("New sale item: " + company.getSaleItem());
    }
}
Enter fullscreen mode Exit fullscreen mode
public class Client {

    public static void main(String[] args) {
        Company nike = new Company("Nike"); // concrete subject

        IAccount john = new Account("John");
        IAccount david = new Account("David");

        // John starts following Nike Inc.
        nike.registerAccount(john);
        nike.setSaleItem("Nike Zoom"); // Releases a new item
        System.out.println("**********************");

        // David becomes a new follower to Nike Inc.
        nike.registerAccount(david);
        nike.setSaleItem("Nike Air"); // Releases a new item
        System.out.println("**********************");

        // John doesn't receive message from Nike Inc. as he removes follow
        nike.removeAccount(john);
        nike.setSaleItem("Air Jordan");
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

John receives a new message from Nike
New sale item: Nike Zoom
**********************
John receives a new message from Nike
New sale item: Nike Air
David receives a new message from Nike
New sale item: Nike Air
**********************
David receives a new message from Nike
New sale item: Air Jordan
Enter fullscreen mode Exit fullscreen mode

Pitfalls

  • The order in which observers receive notification is random.
  • notify() method can be costly as number of setter method that notifies state change in Subject and number of observers.

You can check all the design pattern implementations here.
GitHub Repository

Top comments (2)

Collapse
 
chrismcdonald94 profile image
Chris Mcdonald

Great overview of the Observer Pattern!
In which specific scenarios have you found the Observer Pattern to be most effective? Are there any common performance pitfalls developers should be cautious of when using this pattern in large-scale applications?

Write for us technology

Collapse
 
sota_333ad4b72095606ab40c profile image
Sota

Thank you for your review!
I took your advice into account and edited my blog.
I tried to write specific scenario in "Problem" section, and wrote about some of pitfalls as well.