欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。


欢迎跳转到本文的原文链接:https://honeypps.com/design_pattern/observer/

定义对象见的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的角色

  1. 抽象主题角色(Subject):把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
  2. 具体主题角色(ConcreteSubject):在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
  3. 抽象观察者角色(Observer):为所有的管擦着定义一个接口,在得到主题的通知更新自己。
  4. 具体观察者角色(ConcreteObserver):该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态和主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保持一个指向具体主题角色的引用。

举个简单案例:
1 抽象观察者角色(Observer):

public interface Observer
{public void update(String str);
}

2 抽象主题角色(Subject)

public abstract class Subject
{private List<Observer> list = new ArrayList<>();public void attach(Observer observer){list.add(observer);}public void detach(Observer observer){list.remove(observer);}public void notifyObservers(String str){int len = list.size();for(int i=0;i<len;i++){list.get(i).update(str);}}
}

3 具体主题角色(ConcreteSubject)

public class ConcreteSubject extends Subject
{private String subjectState;public String getState(){return subjectState;}public void setState(String newState){this.subjectState = newState;System.out.println("主题状态为: "+subjectState);this.notifyObservers(subjectState);}
}

4 具体观察者角色(ConcreteObserver)

public class ConcreteObserver implements Observer
{private String observerState;@Overridepublic void update(String state){observerState = state;System.out.println("状态为: "+observerState);}
}
  1. 测试代码:
        ConcreteSubject subject = new ConcreteSubject();Observer observer = new ConcreteObserver();subject.attach(observer);subject.setState("new State");

输出结果:

主题状态为: new State
状态为: new State

推模型和拉模型
在观察者模式中,又分为推模型和拉模型两种方式。

  1. 推模型:主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。
  2. 拉模型:主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

将上面的代码修改一下,变为拉模型案例:
1 抽象观察者角色Observer2,通常是把主题对象当做参数传递

public interface Observer2
{public void update(Subject2 subject);
}

2 具体观察者角色

public class ConcreteObserver2 implements Observer2
{private String observerState;@Overridepublic void update(Subject2 subject){observerState = ((ConcreteSubject2)subject).getState();System.out.println("状态为: "+observerState);}
}

3 抽象主题角色

public abstract class Subject2
{private List<Observer2> list = new ArrayList<>();public void attach(Observer2 observer){list.add(observer);}public void detach(Observer2 observer){list.remove(observer);}public void notifyObservers(){int len = list.size();for(int i=0;i<len;i++){list.get(i).update(this);}}
}

4 具体主题角色

public class ConcreteSubject2 extends Subject2
{private String subjectState;public String getState(){return subjectState;}public void setState(String newState){this.subjectState = newState;System.out.println("主题状态为: "+subjectState);this.notifyObservers();}
}

测试代码:

        ConcreteSubject2 subject = new ConcreteSubject2();Observer2 observer = new ConcreteObserver2();subject.attach(observer);subject.setState("new State");

输出结果:(同上一个案例)

两种模式比较

  1. 推模型假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己取按需要取值。
  2. 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。

优缺点
优点:

  1. Subject和Observer之间是松耦合的,分别可以各自独立改变。
  2. Subject在发送广播通知的时候,无需指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
    缺点:
  3. 松耦合导致代码关系不明显,有时可能难以理解
  4. 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。

适用场景

  1. 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态改变。
  2. 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

JDK中的观察者模式:
java.util.EventListener
javax.servlet.http.HttpSessionBindingListener
javax.servlet.http.HttpSessionAttributeListener
javax.faces.event.PhaseListener


欢迎跳转到本文的原文链接:https://honeypps.com/design_pattern/observer/

参考资料

  1. 《23种设计模式》
  2. 《细数JDK里的设计模式》
  3. 《《JAVA与模式》之观察者模式》

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。


设计模式:观察者模式(Observer)相关推荐

  1. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  2. 设计模式-观察者模式(Observer)-Java

    设计模式-观察者模式(Observer)-Java 目录 文章目录 1.前言 2.示例案例-多人联机对战游戏的设计 3.观察者模式概述 3.1.观察者模式定义 3.2.观察者模式结构 3.3.观察者模 ...

  3. 设计模式-观察者模式(Observer Pattern)

    设计模式-观察者模式 观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应.在观察者模式中,发生改变的对象称为观 ...

  4. 设计模式 - 观察者模式(Observer Pattern) Java内置 用法

    观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...

  5. Android常见设计模式——观察者模式 (Observer Pattern)

    文章目录 1. 前言 2. 观察者模式 2.1 源码 2.2 结构 3. Android中的观察者模式 1. 前言 观察者模式是在代码框架中使用比较高的一个设计模式,常常又叫做订阅/发布模式.而通过这 ...

  6. 设计模式---观察者模式(Observer)和委托事件模型(DEM)

    1 引言 观察者模式,又名发布订阅模式,是一个一对多的关系,当被观察者发生某种变化,对应其观察者做出相应的改变.比如说,某学校研究生实验室有2个学生,2个学生某个上午在实验室,A在玩游戏,B在看电影, ...

  7. C++设计模式--观察者模式(Observer)

    概述 观察者模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 适用场景 以下任一情况下可以使用观察者模式: 当一个抽象模型有两方面,其中一 ...

  8. 趣谈设计模式 | 观察者模式(Observer) :消息的发布与订阅

    文章目录 案例:文章推送 观察者模式 观察者模式的运作流程 观察者模式解决的问题 观察者模式大显身手 总结 要点 应用场景 生产者-消费者模型 VS 观察者模式 完整代码及文档 案例:文章推送 假设我 ...

  9. Java设计模式—观察者模式(Observer pattern)

    故事: 小雪是一个非常漂亮的女孩,漂亮的女孩总是有很多的追求者,而且追求者的队伍在不断的变动,随时有人进入这个队伍,也有人退出.男孩们追求女孩时总是表现出120%的关心,当小雪私自游玩时总是不断收到追 ...

  10. 设计模式:观察者模式--Observer

    一.什么是观察者模式 1.生活中的观察者模式 1.警察抓小偷 在现实生活中,警察抓小偷是一个典型的观察者模式「这以一个惯犯在街道逛街然后被抓为例子」,这里小偷就是被观察者,各个干警就是观察者,干警时时 ...

最新文章

  1. cocos2d-x解决中文乱码问题的几种办法
  2. avue form提交变为不可编辑_教程42——富文本编辑器的原理(项目)
  3. python3.6执行pip3时 Unable to create process using ''
  4. Webservice开发之xsd中开发登录请求的响应接口
  5. oracle redo删除,意外删除redo的恢复
  6. php字符串类型详解,php数字类型之字符串类型详解
  7. Python语言 目录
  8. JS 和 Java 中URL特殊字符编码方式
  9. jquery_Ajax
  10. 海外资管业价格战有多疯狂?史上首个零费率基金横空出世
  11. Fiddler抓包工具之详细使用步骤(超详细)
  12. 安卓手机如何打开.crx文件_crx文件怎么打开
  13. Same Parity Summands
  14. A Game of Thrones(104)
  15. SPSSModeler的下载与安装
  16. 多个系统间是怎么保证统一登录的
  17. websocket连接不成功的原因
  18. “长不大”的云计算第一股
  19. php设计模式(四):行为型模式
  20. ds6708 symbol 驱动_SymbolDS6708

热门文章

  1. bert模型中的[CLS]、[UNK]、[SEP]
  2. airflow零基础入门
  3. 清华裴丹:AIOps 落地路线图
  4. CDH集群调优:内存、Vcores和DRF
  5. 【转】学习笔记:GoogLeNet
  6. 20135337朱荟潼——实验三
  7. 电脑文件系统的管理总结
  8. 下载视频的一种简便方法
  9. substr(IndexAction,1,-6)
  10. T-SQL笔记6:GO