设计模式_观察者模式(18)

来源:互联网 发布:ecshop 2.0数据字典 编辑:程序博客网 时间:2024/06/05 20:14
  • 什么是观察者模式
  • 观察者模式的例子
  • 观察者模式的优缺点
  • 观察者模式的使用场景
  • 闲言碎语

什么是观察者模式

   我们不管自己定没定过报纸或者牛奶,想必都知道大体的流程.我们告诉奶站或者报社我们需要订购他们的产品.他们就会把他们的内容定时定点送到我们手里.而在程序中,我们往往也会有这样的需求,可能某些系统要知道一个系统的状态变换.这时我们就会用到观察者模式去解决这种问题.观察者模式总的来说分为四个部分:

     一、主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法。

     二、观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法。

     三、具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

     四:具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

  UML:

  


观察者模式的例子

观察者接口

package com.designPattern.observer;/** * 观察者接口.可以通俗的认为是我们客户需要做的事情 *  * @author Jason * */public interface Oserver {public void accept();}

主体接口

package com.designPattern.observer;/** * 被观察者的接口.我们可以通俗的认为是奶站或者报社需要做的事情 *  * @author Jason * */public interface Subject {// 添加一个观察者(订购者)public void addOserver(Oserver oserver);// 删除一个观察者(订购者)public void deleteOserver(Oserver oserver);// 通知观察者(可以认为送奶或送报)public void notifyObserver();}

具体主题

package com.designPattern.observer;import java.util.HashSet;import java.util.Set;/** * 具体的被观察者 *  * @author Jason * */public class MengNiuSubject implements Subject {private Set<Oserver> oservers;/* * 构造函数,实例化观察者容器 */public MengNiuSubject() {oservers = new HashSet<Oserver>();}@Override // 添加观察者public void addOserver(Oserver oserver) {oservers.add(oserver);}@Overridepublic void deleteOserver(Oserver oserver) {oservers.remove(oserver);}@Override // 通知观察者public void notifyObserver() {// 以下语句只有java8以上版本才能编译通过oservers.forEach(n -> {n.accept();});}}

具体观察者

package com.designPattern.observer;/** * 具体的观察者 *  * @author Jason * */public class CustomerOserver implements Oserver {private String name;public CustomerOserver(String name) {this.name = name;}@Overridepublic void accept() {// 接收消息System.out.println(name + "收到内容");}}

测试用例

package com.designPattern.observer;import org.junit.Test;/** * 测试用例 *  * @author Jason * */public class TestCase {@Testpublic void test() {Oserver zhangsan = new CustomerOserver("张三");Oserver lisi = new CustomerOserver("李四");Subject mengniu = new MengNiuSubject();mengniu.addOserver(zhangsan);mengniu.addOserver(lisi);mengniu.notifyObserver();}}

观察者模式的优缺点

 优点:

    1、当两个对象之间送耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间送耦合。主题所知道只是一个具体的观察者列表,每一个具体观察者都符合一个抽象观察者的接口。主题并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。

    2、观察者模式支持“广播通信”。主题会向所有的观察者发出通知。

    3、观察者模式符合“开闭原则”的要求。

 缺点:

    1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进  行循环调用,可能导致系统崩溃。

    3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。


观察者模式的使用场景

   1) 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
   2) 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
   3) 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

闲言碎语

  java8内部已经为我们实现的发布-订阅(观察者模式).我们可以很方便的使用它.总的来说观察者模式在日常中使用频率是相当高的.不管是spring还是mq我们都可以看见他的身影!最近工作中也会用到她,如果以后在用的过程中遇到什么坑在写!