观察者模式是定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。 优点:
观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;
观察者模式在观察目标和观察者之间建立一个抽象的耦合;
观察者模式支持广播通信;
观察者模式符合开闭原则(对拓展开放,对修改关闭)的要求。
缺点:
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
在观察者模式中有如下角色:
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象;
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知;
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己;
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
观察者模式实现代码如下。
1)定义观察者(消息接收方)
/\* \* 观察者(消息接收方) \*/
interface Observer {
public void update(String message);
}
/\* \* 具体的观察者(消息接收方) \*/
class ConcrereObserver implements Observer {
private String name;
public ConcrereObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + ":" + message);
}
}
2)定义被观察者(消息发送方)
/\* \* 被观察者(消息发布方) \*/
interface Subject {
// 增加订阅者
public void attach(Observer observer);
// 删除订阅者
public void detach(Observer observer);
// 通知订阅者更新消息
public void notify(String message);
}
/\* \* 具体被观察者(消息发布方) \*/
class ConcreteSubject implements Subject {
// 订阅者列表(存储信息)
private List<Observer> list = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
list.add(observer);
}
@Override
public void detach(Observer observer) {
list.remove(observer);
}
@Override
public void notify(String message) {
for (Observer observer : list) {
observer.update(message);
}
}
}
3)代码调用
public class ObserverTest {
public static void main(String[] args) {
// 定义发布者
ConcreteSubject concreteSubject = new ConcreteSubject();
// 定义订阅者
ConcrereObserver concrereObserver = new ConcrereObserver("老王");
ConcrereObserver concrereObserver2 = new ConcrereObserver("Java");
// 添加订阅
concreteSubject.attach(concrereObserver);
concreteSubject.attach(concrereObserver2);
// 发布信息
concreteSubject.notify("更新了");
}
}
程序执行结果如下:
老王:更新了
Java:更新了