Learning Design Pattern Notes - Observer Pattern

1. Definition

One-to-many dependencies between objects are defined so that when an object changes state, all of its dependencies are notified and automatically updated.

For example: newspaper subscription service, publisher and subscriber.

2. Role

1. Subject, subject interface, the object uses this interface to register as an observer, or to remove itself from the observer.

2. Observer, observer interface, a topic can have multiple observers. All potential observers must implement the observer interface, which has only one method, update(), which is called when the subject changes.

3. ConcreteObserver, a specific observer, can be any class that implements the observer interface. Observers must register with a specific topic in order to receive updates.

4. ConcreteSubject, a specific subject always implements the topic interface. In addition to the registration and cancellation methods, the specific subject also implements the notifyObserver() method, which is used to update all current observers when the state changes. Specific themes may also have methods for setting and getting status.

3. The power of loose coupling

When two objects are loosely coupled, they can still interact, but they are less aware of each other's details.

The Observer pattern provides an object design that provides loose coupling between subjects and observers.

The reason why loosely coupled design allows us to build a flexible OO system that can cope with changes is because the interdependence between objects is reduced to a minimum.

4. Points to note

1. Observers can observe multiple targets, but multiple update methods need to be implemented. One update method corresponds to one target. Avoid business confusion.

2. A target can have multiple observers, and notifications are made by traversing the observers.

3. The observer depends on the target object. When registering, you need to add the observer object reference to the properties of the target object.

4. When setting a value, you can first determine whether the value has been updated, then update the status, and then determine whether to set the value and call the method.

5. You can inject the target into Spring's IOC container, and then inject a registration management class in Spring to register and manage observers. When the bean is initialized, the observer is injected into the target object.

6. Multiple observer model objects cannot have execution order dependencies.

7. Pull the model and pass the target implementation object in the update method. Push the model and only pass the required data information in the update method. Generally, the pull model is used to easily obtain all data of the target object and facilitate business expansion.

5. Naming suggestions (publish and subscribe model)

1. For the definition of the target interface, it is recommended to follow the name with subject;

2. For the definition of the observer interface, it is recommended to follow the name with observer;

3. The update method of the observer interface is recommended to be named update.

4. It is recommended to add concrete in front of the implementation class.

6. Diagram of the calling sequence of the observer mode

1. Maintain the interface, create the target object, create the observer object, and register the observer object with the target object.

2. Run the interface, change the status of the target object, notify all registered observer objects to perform corresponding processing, call back the target object, and obtain the corresponding data.

7. Thought Notes

1. Create a topic interface, providing three methods (add method, delete method, notification method) and a collection attribute (the subscriber's interface reference collection).

2. Theme interface implementation class. The class that implements the theme interface is the object model that needs to save values. It performs specific method operations for data notification. When the attribute parameters in this class change, the notify method is triggered.

3. In the notify method, traverse the subscriber interface reference object, use the subscriber object to call the update method, and pass in the topic interface implementation class object to pull the model.

4. In the pull model method, subscribers can obtain data information in the topic interface implementation class and perform business operations according to their own needs.

5. Create an observer interface. The observer interface only provides one public update method, update(), and the parameters can be subject interface implementation class objects.

6. The observer interface implementation class implements update(), in which business implementation operations are performed based on obtaining the status parameter values ​​in the subject interface implementation class.

advantage

1. Decoupling the observer and the target.

2. Dynamic linkage is realized, just add registered observers.

3. Support broadcast communication

shortcoming

1. Each one needs to call update, which may cause unnecessary performance consumption.

8. Sample code block

1. Observer registration manager

package com.fly.simpletools.service.observer;

import com.fly.simpletools.service.observer.observer.ConcreteOneObserver;
import com.fly.simpletools.service.observer.observer.ConcreteTwoObserver;
import com.fly.simpletools.service.observer.subject.Subject;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author Mr_Fei
 * @description 观察者注册器
 * @date 2020-07-19 16:16
 */
@Component
public class RegisterObserverHandler {

    @Resource
    private Subject subject;

    @Bean
    private void register() {
        //注册观察者1
        subject.addObserver(new ConcreteOneObserver());
        //注册观察者2
        subject.addObserver(new ConcreteTwoObserver());
    }
}

2. Theme interface

package com.fly.simpletools.service.observer.subject;

import com.fly.simpletools.service.observer.observer.Observer;

/**
 * @author Mr_Fei
 * @description 自己实现的主题接口
 * @date 2020-07-19 16:18
 */
public interface Subject {

    /**
     * @param observer 观察者
     * @author Mr_Fei
     * @date 2020/7/19 16:35
     * @description 注册观察者接口
     */
    void addObserver(Observer observer);

    /**
     * @param observer 观察者
     * @author Mr_Fei
     * @date 2020/7/19 16:35
     * @description 移除观察者
     */
    void deleteObserver(Observer observer);

    /**
     * @author Mr_Fei
     * @date 2020/7/19 16:35
     * @description 通知观察者
     */
    void notifyObserver();

    /**
     * @author Mr_Fei
     * @date 2020/7/19 16:35
     * @description 设置改变状态
     */
    void setChanged();
}

3. Theme implementation class

package com.fly.simpletools.service.observer.subject;

import com.fly.simpletools.service.observer.observer.Observer;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Mr_Fei
 * @description 主题实现类
 * @date 2020-07-19 16:22
 */
@Component
public class ConcreteSubject implements Subject {

    /**
     * 传递通知内容
     */
    private Object content;
    /**
     * 存放观察者的集合
     */
    private List<Observer> observers = new ArrayList<>();
    /**
     * 判断是否内容发生变化
     */
    private boolean changed = false;

    @Override
    public void addObserver(Observer observer) {
        if (observer != null) {
            this.observers.add(observer);
        }
    }

    @Override
    public void deleteObserver(Observer observer) {
        if (observer != null) {
            this.observers.remove(observer);
        }
    }

    @Override
    public void notifyObserver() {
        if (observers.isEmpty() || !changed) {
            return;
        }
        for (Observer observer : observers) {
            observer.update(this, content);
        }
        this.changed = false;
    }

    @Override
    public void setChanged() {
        this.changed = true;
    }

    public Object getContent() {
        return content;
    }

    /**
     * @param content 内容
     * @author Mr_Fei
     * @date 2020/7/19 16:36
     * @description set方法判断值是否发生改变,改变则通知观察者
     */
    public void setContent(Object content) {
        if (content != this.content) {
            this.setChanged();
        }
        this.content = content;
        this.notifyObserver();
    }

}

4. Observer interface

package com.fly.simpletools.service.observer.observer;

import com.fly.simpletools.service.observer.subject.Subject;

/**
 * @author Mr_Fei
 * @description 观察者接口
 * @date 2020-07-19 16:19
 */
public interface Observer {

    /**
     * @param subject 主题对象,拉方式参数
     * @param arg     消息内容,推方式参数
     * @author Mr_Fei
     * @date 2020/7/19 16:20
     * @description 更新方法
     */
    void update(Subject subject, Object arg);

}

5. Observer implementation 1

package com.fly.simpletools.service.observer.observer;

import com.fly.simpletools.service.observer.subject.Subject;
import com.fly.simpletools.service.observer.subject.ConcreteSubject;

/**
 * @author Mr_Fei
 * @description 观察者1
 * @date 2020-07-19 16:26
 */
public class ConcreteOneObserver implements Observer {

    @Override
    public void update(Subject subject, Object arg) {
        ConcreteSubject testSubject = (ConcreteSubject) subject;
        //进行业务操作
        System.out.println("TestOneObserverImpl收到主题通知消息内容:" + testSubject.getContent());
    }
}

6. Observer implementation 2

package com.fly.simpletools.service.observer.observer;

import com.fly.simpletools.service.observer.subject.Subject;
import com.fly.simpletools.service.observer.subject.ConcreteSubject;

/**
 * @author Mr_Fei
 * @description 观察者2
 * @date 2020-07-19 16:26
 */
public class ConcreteTwoObserver implements Observer {

    @Override
    public void update(Subject subject, Object arg) {
        ConcreteSubject testSubject = (ConcreteSubject) subject;
        //进行业务操作
        System.out.println("TestTwoObserverImpl收到主题通知消息内容:" + testSubject.getContent());
    }
}

 

 

 

おすすめ

転載: blog.csdn.net/qq_42080073/article/details/107448108