This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

Today, we’re going to start learning about one of the behavioral design patterns: the observer pattern.

Why did you learn behavioral design patterns before you finished learning structural design patterns?

Because I want to study the relatively common design patterns first, the structural design patterns: facade, composition, and share patterns are relatively less common, so I will skip these design patterns first, and finally study these less common design patterns.

Behavioral design patterns mainly solve the problem of “interaction between classes and objects”.

introduce

The Observer Design Pattern is also called the publish-subscribe Design Pattern.

Official definition: Defines a one-to-many dependency between objects in which all dependent objects are notified and automatically updated when an object’s state changes.

The observer mode usually contains the following roles:

  • Subject: A target, also known as a Subject, is an object being observed. An observation target can accept any number of observers to observe. It provides a series of methods to add and remove observer objects. It also defines the notify method (). The target class can be an interface, an abstract class or a concrete class.
  • ConcreteSubject: A concrete target is a subclass of the target class. It usually contains frequently changing data and notifies its observers when its state changes. It also implements the abstract business logic methods (if any) defined in the target class. If the target class is not extended, the concrete target class can be omitted.
  • Observer: An Observer will respond to the change of the observation object. An Observer is generally defined as an interface, which declares the method collect() to update data. Therefore, it is also called abstract Observer.
  • ConcreteObserver: In the ConcreteObserver, a reference to the ConcreteObserver is maintained. It stores the ConcreteObserver states that correspond to the ConcreteObserver states. It implements the update() method defined in the abstract Observer Observer.

In general, the dependent object is called the observed, and the dependent object is called the observer. Looking directly at the above concepts may be a bit of a headache, but let’s look at the specific code implementation to help you understand.

Principle and Implementation

Abstract target (Subject)

public interface Subject {

    // Register the observer
    void registerObserver(Observer observer);

    // Remove the observer
    void removeObserver(Observer observer);

    // Notify the observer
    void notifyObservers(String message);

}
Copy the code

Abstract Observer

public interface Observer {

    // A response to a change in the observation object
    void update(String message);

}
Copy the code

Concrete object

public class ConcreteSubject implements Subject {

    private List<Observer> observers = new ArrayList<>();

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        for(Observer observer : observers) { observer.update(message); }}}Copy the code

ConcreteObserver (ConcreteObserverOne, ConcreteObserverTwo)

public class ConcreteObserverOne implements Observer {
    @Override
    public void update(String message) {
        // Get message notifications and execute your own logic
        System.out.println("Observer One is informed:"+ message); }}public class ConcreteObserverTwo implements Observer {
    @Override
    public void update(String message) {
        // Get message notifications and execute your own logic
        System.out.println("Observer Two is informed:"+ message); }}Copy the code

Test

public class Test {

    public static void main(String[] args) {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        concreteSubject.registerObserver(new ConcreteObserverOne());
        concreteSubject.registerObserver(new ConcreteObserverTwo());
        concreteSubject.notifyObservers("Java is number one!"); }}Copy the code

Results:

The above code is considered “template code” for the observer pattern and reflects the alternative design ideas. In a real development scenario, you don’t have to stick to the above template code, but you can adapt it to the business scenario, but the design idea is the same.

Application scenarios

  • An abstract model has two aspects, one of which depends on the other. Encapsulate these aspects in separate objects so that they can be changed and reused independently.
  • A change in one object will cause one or more other objects to change, and not knowing exactly how many objects will change can reduce the coupling between objects.
  • One object must notify other objects without knowing who they are.
  • You need to create A chain of triggers in the system where the behavior of object A affects object B, and the behavior of object B affects object C… You can use observer mode to create a chain trigger mechanism.

The observer pattern can be applied in a wide range of scenarios, from decoupling at the code level to system decoupling at the architecture level, as well as some product design ideas. For example, email subscription and RSS Feeds are all observer patterns in nature.

conclusion

In fact, what design patterns are about is decoupling. The creative pattern decouples the code created and used, the structural pattern decouples the code of different functions, and the behavioral pattern decouples the code of different behaviors. Specifically, the observer pattern decouples the code of the observer and the observed.