1、定义
当对象间存在一对多的映射关系时,为了检测某个对象的改变,能够及时通知所依赖这个对象的所有对象都做响应的修改,这种模式被称为观察者模式。
2、优点
- 观察者和被观察者是抽象耦合的,不存在强依赖关系。
- 建立起一种一触即发的机制,当被观察对象发生改变时,能够及时被发现,并做相应修改。
3、缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
4、使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
5、注意事项
- JAVA 中已经有了对观察者模式的支持类。
- 避免循环引用。
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
6、实现
观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。
6.1、创建 Subject 类
/**
* desc: 被观察对象
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:11
*/
public class Subject {
// 观察者列表
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
// 通知观察者,对象变了
notifyAllObservers();
}
/**
* 添加观察者对象到观察者列表中;
* @param observer 观察者
*/
public void attach(Observer observer){
observers.add(observer);
}
/**
* 通知所有观察者
*/
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
6.2、创建观察者抽象类
/**
* desc: 抽象的观察者对象类
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:12
*/
public abstract class Observer {
// 被观察的对象
protected Subject subject;
/**
* 抽象的更新通知方法
*/
public abstract void update();
}
6.3、创建观察者实现类
/**
* desc: 观察者实现类
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:14
*/
public class BinaryObserver extends Observer{
private Subject subject;
public BinaryObserver(Subject subject) {
this.subject = subject;
subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) );
}
}
/**
* desc:
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:27
*/
public class HexaObserver extends Observer {
private Subject subject;
public HexaObserver(Subject subject) {
this.subject = subject;
subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hexa String: " + Integer.toHexString( subject.getState() ) );
}
}
/**
* desc:
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:27
*/
public class OctalObserver extends Observer {
private Subject subject;
public OctalObserver(Subject subject) {
this.subject = subject;
subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) );
}
}
6.4、测试类
/**
* desc:
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/17 11:28
*/
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new BinaryObserver(subject);
new OctalObserver(subject);
new HexaObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
6.5、运行结果
First state change: 15
Binary String: 1111
Octal String: 17
Hexa String: f
Second state change: 10
Binary String: 1010
Octal String: 12
Hexa String: a