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.

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.

  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

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

原文链接:Observer Pattern

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容