定义:

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

结构:(书中图,侵删)

一个抽象的观察者接口,拥有一个更新方法
若干个具体的观察者类
一个抽象的subject类,包含一个抽象观察者的集合,并拥有增加、删除观察者的方法,以及一个通知的方法
若干个具体subject类

实例:

举个看球赛的例子吧。
假设比赛在主场比。
subject就是球赛赛况;具体的subject分为现场看、电视上看。
然后观察者分为主场球迷,客场球迷。
抽象观察者接口(球迷接口):
package designpattern.observer;public interface Fans {public void react(String result);
}

具体球迷类:
主场球迷:

package designpattern.observer;public class HomeFans implements Fans {@Overridepublic void react(String result) {System.out.print("主场球迷:");if (result.equals("win")) {System.out.println("Yes! 我们赢啦,主场就是牛批!!!");} else {System.out.println("输了,哎...");}}}

客场球迷:

package designpattern.observer;public class AwayFans implements Fans {@Overridepublic void react(String result) {System.out.print("客场球迷:");if (result.equals("win")) {System.out.println("输了,哎...");} else {System.out.println("Yes! 客场都赢啦,牛批!!!");}}}

抽象subject接口(比赛接口):

package designpattern.observer;import java.util.ArrayList;
import java.util.List;public interface Match {List<Fans> fansList = new ArrayList<>();// 这一句void addFans(Fans fans);void removeFans(Fans fans);void notifyResult(String result);}

注释的那一句说明一下:
书中这句就是写在接口里的,但是写在这里就是一个全局的,所有子类都共用这同一个list
但我自己感觉各个子类所需要通知的观察者应该是不一定一样的,所以我是改到了子类中
但我后来写总结的时候回看定义,发现,总结写的就是“一对多的依赖关系”,既然不是多对多,那自然观察者就是统一调配的
只不过还是感觉有点怪怪的,往集合里添加删除观察者的方法是不是改成静态方法会好一点?
不然,必须要实例化一个子类的对象才能调用。
现场看比赛:

package designpattern.observer;import java.util.ArrayList;
import java.util.List;public class MatchOnTheSpot implements Match {// List<Fans> fansList = new ArrayList<>();
@Overridepublic void addFans(Fans fans) {fansList.add(fans);}@Overridepublic void removeFans(Fans fans) {fansList.remove(fans);}@Overridepublic void notifyResult(String result) {for (Fans fans : fansList) {fans.react(result);}}
}

电视看比赛:

package designpattern.observer;import java.util.ArrayList;
import java.util.List;public class MatchOnTheTV implements Match {// List<Fans> fansList = new ArrayList<>();
@Overridepublic void addFans(Fans fans) {fansList.add(fans);}@Overridepublic void removeFans(Fans fans) {fansList.remove(fans);}@Overridepublic void notifyResult(String result) {for (Fans fans : fansList) {fans.react(result);}}
}

此例中,两个子类的代码完全相同,可以把接口改成抽象类,然后把方法写到父类中,我这里就不改了。
客户端:

package designpattern.observer;public class Client {public static void main(String[] args) {HomeFans homeFans = new HomeFans();AwayFans awayFans = new AwayFans();// 现场看Match match = new MatchOnTheSpot();match.addFans(homeFans);match.addFans(awayFans);System.out.println("主场赢啦~");match.notifyResult("win");System.out.println("===========================");// 电视上看match = new MatchOnTheTV();System.out.println("主场输啦~");match.notifyResult("lose");}
}

结果输出:
主场赢啦~
主场球迷:Yes! 我们赢啦,主场就是牛批!!!
客场球迷:输了,哎...
===========================
主场输啦~
主场球迷:输了,哎...
客场球迷:Yes! 客场都赢啦,牛批!!!

总结:

(按理说总结才是精华,但我每次总结都不知道要写点什么,可能是理解得还不够深刻吧。)
这个设计模式可以在一个对象改变的同时需要其他对象也跟着改变的时候使用。
好处说来说去就是那么几点,解除了观察者和通知者之间的耦合,将依赖转移给抽象,符合依赖倒转原则。
缺点嘛,就是这里的通知调用的都是同一方法(本例中就是notifyResult()方法),而实际应用中,可能是各种各样的方法名,还有可能有一些是别人已经封装好的方法,根本不可能去继承你的抽象观察者接口。
书中使用了一个叫事件委托的技术来解决这个问题,然后java中并没有直接的封装,实现这个需要用到反射,稍微有点麻烦,我这里就先不实现了,等以后再回来补全。有兴趣的可以自己去试一下。

转载于:https://www.cnblogs.com/imoqian/p/10771406.html

设计模式 | 观察者模式/发布-订阅模式(observer/publish-subscribe)相关推荐

  1. 设计模式-观察者模式 发布/订阅模式

    设计模式-观察者模式 发布/订阅模式 代码 观察者接口 public interface IHanFeiZi{// 当吃早饭时public void havBreakFast();// 进行娱乐活动时 ...

  2. RabbitMQ发布/订阅模式(Publish/Subscribe)

    工作队列模式是直接在生产者与消费者里声明好一个队列,这种情况下消息只会对应同类型的消费者. 举个用户注册的列子:用户在注册完后一般都会发送消息通知用户注册成功(失败).如果在一个系统中,用户注册信息有 ...

  3. python 设计模式 观察者模式(发布订阅模式)

    发布订阅模式 观察者模式应用比较广泛,又被称为"发布-订阅"模式.它用来定义对象间一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新. 问题1 ...

  4. RabbitMQ指南之三:发布/订阅模式(Publish/Subscribe)

    在上一章中,我们创建了一个工作队列,工作队列模式的设想是每一条消息只会被转发给一个消费者.本章将会讲解完全不一样的场景: 我们会把一个消息转发给多个消费者,这种模式称之为发布-订阅模式. 为了阐述这个 ...

  5. 每日学习一个设计模式--观察者模式(发布-订阅模式)

    定义 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.这种模式有时又称作发布-订阅模式.模型-视图模式,它 ...

  6. JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  7. 【RabbitMQ】基础三:发布与订阅模式(Publish/Subscribe)

    [RabbitMQ]基础三:发布与订阅模式(Publish/Subscribe) 1. 订阅模式 2. 发布与订阅模式说明 3. 代码示例 3.1 生产者 3.2 消费者 3.3 测试 4. 总结 1 ...

  8. 游戏服务器架构-设计模式之发布订阅模式

    发布订阅模式场景 熟悉消息中间件的同学应该对发布/订阅模式(Publish Subscribe Pattern)并不陌生.即使你不了解消息中间件,那么在平时生活中发布/订阅模式也是非常常见的场景. 比 ...

  9. 从东京奥运会看js设计模式之发布订阅模式

    开篇废话:本篇文章介绍发布-订阅模式,想必很多人听说过有一种观察者模式,网上既有资料说这是两种不同的设计模式,也有说这是一种模式,我倾向于认同他们是同一种设计模式.不必过于纠结 开篇楔子:东京奥运会已 ...

最新文章

  1. 使用nexus来搭建Nuget私服
  2. c# 自定义文件关联程序
  3. android authtype=1,【报Bug】plus.screen.lockOrientation在android里引起闪退
  4. C++ Testing Framework
  5. 1087 All Roads Lead to Rome (30 分)【难度: 一般 / Dijkstra】
  6. 大数据领域33个预测,开启未知的2016
  7. php文件锁解锁是删除对应的文件_软件 | 文件解锁强制删除工具 Wise Force Deleter v1.49...
  8. java数组与C++数组间的区别
  9. 24张最新可视化大屏模板,各行业数据直接套用
  10. 局部替换算法最小生成树
  11. 今日恐慌与贪婪指数为28,等级由极度恐慌转为恐慌
  12. Pandas详解十之Dropna滤除缺失数据
  13. XXE漏洞详解与利用
  14. 怎样制作网关服务器,如何设计自己的网关(一)
  15. 金融借贷平台大数据风控解决方案
  16. 【面试题集 —— No.01】常见图片格式BMP、JPG/JPEG、PNG、GIF、TIFF、SVG的区别
  17. 展望:可见光通信技术标准体系建设
  18. 《锋利的jQuery》读书要点笔记7——制作商城网页:网站脚本
  19. 【Arduino基础】一位数码管实验
  20. NAS与NAS数据同步

热门文章

  1. HTTP与HTTPS(自制漫画图解)
  2. Java基础知识之什么是集合框架
  3. 2019湖南省职业院校技能竞赛集训开班典礼
  4. Photon PUN和Photon Server连接问题及解决方法(Unity开发)
  5. Unknown version string [4.0]. Default version will be used.
  6. 微信小程序开发笔记 基础篇②——微信小程序 手动查看和代码查看开发者ID(AppID)
  7. 分享一个Python 在线编辑器
  8. XML/XSD/XSLT
  9. DDoS 攻击继续激增
  10. 【Linux】日志 日志管理服务 日志轮替