专栏目录
- 创建型模式: 工厂三兄弟 , 单例模式 , 原型模式 , 建造者模式
- 结构型模式: 适配器模式 , 桥接模式 , 组合模式 , 装饰器模式, 外观模式(门面模式), 享元模式, 代理模式
- 行为型模式: 职责链模式, 命令模式, 解释器模式, 迭代器模式, 中介者模式, 备忘录模式, 观察者模式, 状态模式, 策略模式, 模板方法, 访问者模式
观察者模式的意图,解决的问题,什么时候使用
在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心;还有,当我们开车到交叉路口时,遇到红灯会停,遇到绿灯会行。这样的例子还有很多,例如,股票价格与股民、微信公众号与微信用户、气象局的天气预报与听众、小偷与警察等。
在软件世界也是这样,例如,Excel 中的数据与折线图、饼状图、柱状图之间的关系;MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者。所有这些,如果用观察者模式来实现就非常方便。
1.观察者模式
观察者(Observer)模式,指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
2.观察者模式中的角色
组成(角色) | 作用 |
---|---|
抽象主题(Subject)角色 | 也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。 |
具体主题(Concrete Subject)角色 | 也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。 |
抽象观察者(Observer)角色 | 它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。 |
具体观察者(Concrete Observer)角色 | 实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。 |
结构图:
其代码结构如下:
package net.biancheng.c.observer;
import java.util.*;
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new ConcreteSubject();
Observer obs1 = new ConcreteObserver1();
Observer obs2 = new ConcreteObserver2();
subject.add(obs1);
subject.add(obs2);
subject.notifyObserver();
}
}
//抽象目标
abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>();
//增加观察者方法
public void add(Observer observer) {
observers.add(observer);
}
//删除观察者方法
public void remove(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class ConcreteSubject extends Subject {
public void notifyObserver() {
System.out.println("具体目标发生改变...");
System.out.println("--------------");
for (Object obs : observers) {
((Observer) obs).response();
}
}
}
//抽象观察者
interface Observer {
void response(); //反应
}
//具体观察者1
class ConcreteObserver1 implements Observer {
public void response() {
System.out.println("具体观察者1作出反应!");
}
}
//具体观察者1
class ConcreteObserver2 implements Observer {
public void response() {
System.out.println("具体观察者2作出反应!");
}
}
运行结果:
具体目标发生改变...
--------------
具体观察者1作出反应!
具体观察者2作出反应!
JDK中已经提供了标准的观察者模式规范,实现Observer接口成为观察者,继承Observable类称为目标类(可被观察)。
3.观察者模式优缺点、使用场景
优点:
- 1.降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
- 2.目标与观察者之间建立了一套触发机制。支持广播通讯,简化了一对多系统的设计难度。
缺点:
- 1.目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 2.当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
适用场景:
在软件系统中,当系统一方行为依赖另一方行为的变动时,可使用观察者模式松耦合联动双方,使得一方的变动可以通知到感兴趣的另一方对象,从而让另一方对象对此做出响应。
- 1.对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
- 2.当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 3.实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
- 4.多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。
参考文章:http://c.biancheng.net/view/1390.html