1.什么是观察者模式
观察者模式(Observer),是一种行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作,进一步明确对象的职责。相比来说,创建型模式关注对象的创建过程,结构型模式关注对象和类的组合关系。
2.模式的职责
观察者模式主要用于1对N的通知。当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出相应。
实现有两种方式:
推:每次都会把通知以广播的方式发送给所有观察者,所有的观察者只能被动接收。
拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定。
3.模式的实现
创建Observer接口
package com.designpattern.observer;
/**
* @description: {@link Observer}观察者接口,用来存放观察者共有方法,由{@link ObserverA},{@link ObserverB}等实现
* @author: Codegitz
* @create: 2020-05-19 22:16
**/
public interface Observer {
void update(Subject subject);
}
创建被观察者Subject类
package com.designpattern.observer;
import java.util.ArrayList;
import java.util.List;
/**
* @description: {@link Subject}被观察对象,可注册唤醒{@link Observer}观察者
* @author: Codegitz
* @create: 2020-05-19 22:17
**/
public class Subject {
//被观察者的状态
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
this.notifyAllObserver();
}
//维护一个观察者列表
private List<Observer> observers = new ArrayList<>();
//注册
public void registerObserver(Observer observer){
observers.add(observer);
}
//移出
public void removeObserver(Observer observer){
observers.remove(observer);
this.notifyAllObserver();
}
//更新列表里的观察者
public void notifyAllObserver(){
for (Observer observer: observers){
observer.update(this);
}
}
}
实现Observer
接口,有ObserverA
, ObserverB
, ObserverC
三种观察者,这里只贴一份代码,其他的差不多。
package com.designpattern.observer;
/**
* @description: 观察者A,实现{@link Observer}
* @author: Codegitz
* @create: 2020-05-19 22:30
**/
public class ObserverA implements Observer {
private Subject subject;
@Override
public void update(Subject subject) {
this.subject = subject;
getMyState();
}
//拼接一下当前观察者类名和更新后的state值
public void getMyState(){
System.out.println("[Observer name: "+this.getClass().getName()+"]--subject.getState(): "+subject.getState());
}
}
测试类
package com.designpattern.observer;
/**
* @description: 测试类
* @author: Codegitz
* @create: 2020-05-19 22:40
**/
public class TestObserver {
public static void main(String[] args) {
//新建一个被观察对象
Subject subject = new Subject();
//三个不同的观察者
Observer observer1 = new ObserverA();
Observer observer2 = new ObserverB();
Observer observer3 = new ObserverC();
//注册三个观察者
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.registerObserver(observer3);
//改变state的值
System.out.println("=======change state value,set state = 100==========");
subject.setState(100);
//移除一个观察者
System.out.println("============remove observer3============");
subject.removeObserver(observer3);
System.out.println("=======change state value,set state = 200==========");
subject.setState(200);
}
}
运行结果如下:
=======change state value,set state = 100==========
[Observer name: com.designpattern.observer.ObserverA]--subject.getState(): 100
[Observer name: com.designpattern.observer.ObserverB]--subject.getState(): 100
[Observer name: com.designpattern.observer.ObserverC]--subject.getState(): 100
============remove observer3============
[Observer name: com.designpattern.observer.ObserverA]--subject.getState(): 100
[Observer name: com.designpattern.observer.ObserverB]--subject.getState(): 100
=======change state value,set state = 200==========
[Observer name: com.designpattern.observer.ObserverA]--subject.getState(): 200
[Observer name: com.designpattern.observer.ObserverB]--subject.getState(): 200
从结果可以看到,在更新被观察者的state值后,被观察者会通知所有的观察对象,把当前的被观察者对象this更新到观察者中,观察者可以进行相应的处理,我这里是直接打印了state的值,这是一种基于’’推’’模式的实现。在观察者被移除后,也会把当前状态更新一次,如果不需要这一步,只需要把removeObserver
方法里的this.notifyAllObserver()
方法去掉。
附完整代码,需要自取,顺便点个star。
4.观察者模式应用场景
关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
事件多级触发场景。
跨系统的消息交换场景,如消息队列、事件总线的处理机制。消息队列应该是很经典的一种实践了。