模式动机
建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将作出相应反应。在此,发生改变的目标称为观察目标,被通知的对象称为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系。
模式定义
定义对象间的一种一对多依赖关系
,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
模式结构
观察者模式包含如下角色:
- Subject: 目标
- ConcreteSubject: 具体目标
- Observer: 观察者
- ConcreteObserver: 具体观察者
时序图
代码实现
//抽象观察者
public interface Observer {
void update(String message);
}
//抽象被观察对象
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyChange();
void setInfomation(String s);
}
//具体观察者
public class RealObserver implements Observer {
private String name;
private String message;
public RealObserver(String name){
this.name=name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到推送消息: " + message);
}
}
//具体被观察对象
public class RealSubject implements Subject{
private List<Observer> observerList=new ArrayList<>();
private String message;
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyChange() {
for (Observer observer:observerList){
observer.update(message);
}
}
public void setInfomation(String s) {
this.message = s;
System.out.println("微信服务更新消息: " + s);
//消息更新,通知所有观察者
notifyChange();
}
}
//客户端
public class Client {
public static void main(String[] args) {
Subject subject=new RealSubject();
Observer userZ=new RealObserver("张三");
Observer userL=new RealObserver("李四");
Observer userW=new RealObserver("王五");
subject.attach(userZ);
subject.attach(userL);
subject.attach(userW);
subject.setInfomation("帮我带一杯奶茶");
System.out.println("+++++++++++++++++++++++++++++++++++++++");
subject.detach(userW);
subject.setInfomation("王五不要奶茶");
}
}
模式分析
- 观察者模式描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。
- 作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publishsubscribe)。
模式优缺点
优点
- 观察者模式可以
实现表示层和数据逻辑层的分离
,并定义了稳定的消息更新传递机制,抽象了更新接口
,使得可以有各种各样不同的表示层作为具体观察者角色。 - 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 观察者模式支持广播通信。
- 观察者模式符合“开闭原则”的要求。
缺点
- 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在
观察者和观察目标
之间有循环依赖
的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
。 - 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。