模式定义
观察者模式定义了一个一对多的依赖关系,让多个观察者对象同时监听一个主题对象
当这个主题对象改变时,会通知所有的观察者,让他们能够自动的更新自己
观察者模式的组成
抽象主题(Subject):把所有的对观察者对象的引用保存在一个集合中,抽象主题提供一个接口,可以注册和移除观察者;
抽象观察者(Observer):为所有的观察者定义一个接口,当主题的数据更新时给登记的观察者提供通知;
具体主题(ConcreteSubject):在具体主题内部状态改变时,给所有登记过的观察者发出通知;
具体观察者(ConcreteObserver):实现抽象观察者提供的更新接口,以便本身的状态能够及时更新;
UML图
Subject.java
/**
* 抽象目标者
*/
public abstract class Subject {
// 保存注册的观察者对象
private List<Observer> mObservers = new ArrayList<>();
//注册观察者对象
public void attach(Observer observer) {
mObservers.add(observer);
System.out.println("Attached an observer");
}
//注销观察者对象
public void detach(Observer observer) {
mObservers.remove(observer);
}
// 通知所有注册的观察者对象
public void nodifyObservers(String newState) {
for (Observer observer : mObservers) {
observer.update(newState);
}
}
}
ConcreteSubject.java
/**
* 具体目标者
*/
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
public void change(String newState) {
state = newState;
System.out.println("ConcreteSubject State:" + state);
//状态发生改变,通知观察者
nodifyObservers(state);
}
}
Observer.java
/**
* 观察者
*/
public interface Observer {
void update(String state);
}
ConcreteObserver.java
/**
*具体观察者
*/
public class ConcreteObserver implements Observer {
// 观察者状态
private String observerState;
@Override
public void update(String state) {
// 更新观察者状态,让它与目标状态一致
observerState = state;
System.out.println("ConcreteObserver State :" + observerState);
}
}
测试类
public class MyClass {
public static void main(String[] args) {
// 创建目标对象
ConcreteSubject concreteSubject = new ConcreteSubject();
// 创建观察者对象
Observer observer = new ConcreteObserver();
// 将观察者对象注册到目标对象上
concreteSubject.attach(observer);
// 改变目标对象的状态
concreteSubject.change("I change");
}
}
运行结果
观察模式的优点
观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
观察者模式在观察目标和观察者之间建立一个抽象的耦合。
观察者模式支持广播通信。
观察者模式符合“开闭原则”的要求。
观察模式的缺点
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。