红灯车过,人停;绿灯人过,车停。天天走在马路上,处处可见红绿灯指挥着咱们何时能够过马路,何时不能过马路。不管是人仍是车,都时刻关注着红绿灯的状态,一旦红绿灯的状态发生了改变,咱们总能第一时间发现,而且作出相应的响应.....说真,红绿灯真的是个伟大的发明。java
说到观察者模式,无非就是观察者和被观察者之间牵扯到的一些关系。在上面的红绿灯例子中,红绿灯就如同被观察者,咱们又称之为观察目标,而人行者或开着车的人就如同观察者,时刻观察着红绿灯的变化,红绿灯一旦发生变化,便会立刻通知观察者,观察者也常常会作出相应的反应。设计模式
下面咱们说下观察者模式的定义:微信
观察者模式定义了对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆获得通知并被自动更新。测试
观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。网站
上面的例子中,红绿灯就至关于一,而路上的人就至关于多,每次红路灯这个目标对象的状态发生变化,就会通知众多的观察者(人)。而观察者通常也会作出对象的响应spa
观察者模式属于行为型模式设计
观察者模式主要解决的问题:一方的状态发生了变化,依赖于这一方的观察者当即能收到通知。code
例如咱们平时订阅的微信公众号,一旦公众号有新的文章发布,订阅者可以当即收到新的文章推送。server
这里须要注意的是,目标对象会把状态的变化通知全部观察者,而无论观察者的具体身份。本身也并不知道通知的这我的到底是谁。对象
观察者模式通常包含以下四个角色:
结构图:
下面具体介绍下这四个角色:
Subject(目标):目标又被称为主题,指被观察的对象,即被观察者。通常咱们会在在目标中定义一个观察者集合,用来管理观察者。一个观察目标能够接受任意数量的观察者来观察,它提供一系列方法来增长和删除观察者对象,如attach()方法与detach()方法;同时也会定义通知方法notify()。目标类能够是接口,也能够是抽象类或具体类,但通常咱们设计为抽象类。
ConcreteSubject(具体目标):具体目标是目标类的子类(接口的实现者),一般它包含有常常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法
Observer(观察者):观察者角色通常是一个接口,它会有一个update方法,当目标对象的状态发生改变时,这个方法就会被调用。
ConcreteObserver(具体观察者):观察者接口的实现者,在这个角色中,将会定义目标对象状态发生变化时所要处理的逻辑。
观察者模式通常的代码实现:
1.目标对象与具体目标对象代码示例
public abstract class Subject { //定义一个观察者集合用于存储全部观察者对象 protected List<Observer> observers = new ArrayList(); //注册方法,用于向观察者集合中增长一个观察者 public void attach(Observer observer) { observers.add(observer); } //注销方法,用于在观察者集合中删除一个观察者 public void detach(Observer observer) { observers.remove(observer); } //声明抽象通知方法 public abstract void notify(); //其余方法 } //具体目标类ConcreteSubject是实现了抽象目标类Subject的一个具体子类 //其典型代码以下所示: class ConcreteSubject extends Subject { //实现通知方法 public void notify() { System.out.println("目标对象状态发生变化了") //遍历观察者集合,调用每个观察者的响应方法 for(Observer obs:observers) { obs.update(); } } }
2.观察者与具体观察者代码示例
interface Observer { //声明响应方法 public void update(); } //在具体观察者ConcreteObserver中实现了update()方法 //其典型代码以下所示: class ConcreteObserver implements Observer { //实现响应方法 public void update() { System.out.println("观察者收到通知,正在作相应的处理") } }
3.测试代码
public class Test{ public static void main(String[] args){ Subject sub = new ConcreteSubject(); sub.attach(new ConcreteObserver()); //假设状态发生了变化调用notify()方法 sub.notify(); } }
4.打印结果
目标对象状态发生变化了 观察者收到通知,正在作相应的处理
优势:
一、从例子中咱们能够看出观察者和被观察者是抽象耦合的,只有轻微的关联关系
二、创建一套触发机制。目标对象一旦发生变化,便会触发广播通知,观察者一旦收到通知,也会触发相应的响应。
缺点:
一、若是一个被观察者对象有不少的直接和间接的观察者的话,将全部的观察者都通知到会花费不少时间。
二、若是在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能致使系统崩溃。
三、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
1.一个抽象模型有两个方面,其中一个方面依赖于另外一个方面。将这些方面封装在独立的对象中使它们能够各自独立地改变和复用。
2.一个对象的改变将致使其余一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,能够下降对象之间的耦合度。
3.一个对象必须通知其余对象,而并不知道这些对象是谁。
4.须要在系统中建立一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可使用观察者模式建立一种链式触发机制
Java语言中也有提供了Observer接口,下一篇简单讲解使用下。
参考书籍:
1.设计模式java版。
2.Head First设计模式
3.菜鸟教程网站
完
关注公个人众号: 苦逼的码农,获取更多原创文章,后台回复 礼包送你一份特别的资源大礼包。