在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

角色组成

抽象主题(Subject)

它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

具体主题(Concrete Subject)

将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有注册过的观察者发出通知。

抽象观察者(Observer)

为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

具体观察者(Concrete Observer)

实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

具体实现


抽象主题(被观察者)

public interface Subject {
    /**
     * 注册观察者
     * @param observer
     */
    void registerObserver(Observer observer);

    /**
     * 移除观察者
     * @param observer
     */
    void removeObserver(Observer observer);

    /**
     * 通知所有观察者
     */
    void notifyAllObserver();
}

具体主题

public class SubjectImpl implements Subject {

    private List<Observer> observerList = new ArrayList<>();
    private String status;

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

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

    @Override
    public void notifyAllObserver() {
        for (Observer observer : observerList) {
            observer.process(status);
        }
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

抽象观察者

public interface Observer {
    void process(String status);
}

具体观察者

public class ObserverA implements Observer {
    @Override
    public void process(String status) {
        System.out.println("A观察者收到了状态变更为【"+status+"】的通知");
    }
}
public class ObserverB implements Observer {
    @Override
    public void process(String status) {
        System.out.println("B观察者收到了状态变更为【"+status+"】的通知");
    }
}

更改状态,来通知到其他观察者

        SubjectImpl subject = new SubjectImpl();

        //注册观察者A
        Observer observerA = new ObserverA();
        subject.registerObserver(observerA);

        //注册观察者B
        Observer observerB = new ObserverB();
        subject.registerObserver(observerB);

        subject.setStatus("进行中");
        System.out.println("被观察者状态变为【进行中】,正在通知观察者们...");
        //通知所有观察者
        subject.notifyAllObserver();
被观察者状态变为【进行中】,正在通知观察者们...
A观察者收到了状态变更为【进行中】的通知
B观察者收到了状态变更为【进行中】的通知

总结

使用场景

  1. 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。
  2. 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,不希望这些对象是紧密耦合的。
  3. 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
02-10 07:04