1、简介:
当对象之间存在一对多关系时,则使用观察者模式。当目标对象发送变化时,则通知他所依赖的所有对象(观察者对象)更新状态。
2、优点:
2.1 观察者与被观察者之间是抽象耦合的
2.2 建立了一套触发机制
3、缺点:
3.1 当一个被观察者有很多直接或间接的观察者时,将所有的观察者通知到会花费大量时间
3.2 如果观察者与目标对象之间存在循环依赖的话,目标对象会触发它们之间的循环调用,可能导致系统崩溃
3.3 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
4、注意事项
4.1 JAVA 中已经有了对观察者模式的支持类。
4.2 避免循环引用。
4.3如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
5、实现
5.1 创建三个类Subject、Observer、Client
5.1.1 Subject是目标对象或目标对象的父类
5.1.1.1 目标对象中应该有一个存放所有观察者的容器以及一个通知方法
5.1.1.2 通知方法中遍历每个观察者,调用Observer中接口的方法(update())进行更新
5.1.2 Observer是观察者接口和实现了接口的实体类
5.1.3 Client是进行测试的客户端
5.2 代码
5.2.1 创建Observer接口
package pattern;
//观察者接口
public interface Obsever {
//调用update()更新观察者的状态
void update(Subject subject);
}
5.2.2 创建主题Subject-目标对象及目标对象的父类
public class Subject {
private List<Obsever> obsevers = new ArrayList<>();
//注册观察者
public void register(Obsever obsever){
obsevers.add(obsever);
}
//移除观察者
public void remove(Obsever obsever){
obsevers.remove(obsever);
}
//通知所有订阅者更新状态
public void notify(Subject subject){
for (Obsever obsever : obsevers) {
obsever.update(subject);
}
}
}
5.2.3 创建目标对象实体类
public class ConcreateSubject extends Subject {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//目标对象的状态发送变化,通知所有的订阅者进行状态更新
this.notify(this);
}
}
5.2.4 创建观察者实体类
public class ObseverA implements Obsever {
private int myState;//myState的值需要与目标对象的state的值保持一致
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
@Override
public void update(Subject subject) {
this.myState =((ConcreateSubject)subject).getState();
}
}
5.2.5 创建Client进行测试
public class Client {
public static void main(String[] args) {
//消息发布者
ConcreateSubject concreate = new ConcreateSubject();
//创建多个观察者对象
ObseverA obsever1=new ObseverA();
ObseverA obsever2=new ObseverA();
ObseverA obsever3=new ObseverA();
//将多个观察者进行注册/订阅
concreate.register(obsever1);
concreate.register(obsever2);
concreate.register(obsever3);
concreate.setState(100);
System.out.println(obsever1.getMyState());
System.out.println(obsever1.getMyState());
System.out.println(obsever1.getMyState());
System.out.println("#################");
concreate.setState(300);
System.out.println(obsever1.getMyState());
System.out.println(obsever1.getMyState());
System.out.println(obsever1.getMyState());
}
}
5.2.6 测试结果