定义:

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

结构:(书中图,侵删)

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

实例:

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

public interface Fans {
public void react(String result);
}
具体球迷类:
主场球迷:

package designpattern.observer;

public class HomeFans implements Fans {

    @Override
public 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 {

    @Override
public 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<>(); @Override
public void addFans(Fans fans) {
fansList.add(fans);
} @Override
public void removeFans(Fans fans) {
fansList.remove(fans);
} @Override
public 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<>(); @Override
public void addFans(Fans fans) {
fansList.add(fans);
} @Override
public void removeFans(Fans fans) {
fansList.remove(fans);
} @Override
public 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中并没有直接的封装,实现这个需要用到反射,稍微有点麻烦,我这里就先不实现了,等以后再回来补全。有兴趣的可以自己去试一下。
 

设计模式 | 观察者模式/发布-订阅模式(observer/publish-subscribe)的更多相关文章

  1. RabbitMQ学习第三记:发布/订阅模式(Publish/Subscribe)

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

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

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

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

    一.发布/订阅(Publish/Subscribe)模式 发布订阅是我们经常会用到的一种模式,生产者生产消息后,所有订阅者都可以收到.RabbitMQ的发布/订阅模型图如下: 1.该模式下生产者并不是 ...

  4. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

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

  5. js设计模式之发布/订阅模式模式

    一.前言 发布订阅模式,基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知. 就和用户 ...

  6. js设计模式之发布订阅模式

    1. 定义 发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知. 订阅者(Subscriber)把自己想订阅的事件注册(Subscri ...

  7. C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

    使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...

  8. SpringBoot事件监听机制及观察者模式/发布订阅模式

    目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...

  9. javaScript设计模式:发布订阅模式

    发布订阅模式的思想是在观察者模式的基础上演变而来,在观察者模式中客户端监听到对象某个行为就触发对应任务程序.而在发布订阅模式中依然基于这个核心思想,所以有时候也会将两者认为是同一种设计模式.它们的不同 ...

随机推荐

  1. Python 简单实现数学四则运算

    GitHub地址:https://github.com/compassblog/PythonExercise 一.题目描述 (1)能自动生成小学四则运算题目: (2)能支持真分数的四则运算: 二.实现 ...

  2. vue config.js配置生产环境和发布环境不同的接口地址问题

    第一步,分别设置不同的接口地址 首先,我们分别找到下面的文件: /config/dev.env.js /config/prod.env.js 其实,这两个文件就是针对生产环境和发布环境设置不同参数的文 ...

  3. 第二章之S5PV210在BL1中点亮LED灯

    1,u-boot中第一个入口在./arch/arm/cpu/armv7/start.S 翻到153行:如下图 前面都是进行一些基本设置,不用管. cpu_init_cp15设置协处理器, cpu_in ...

  4. 字符串转json以及获取域名的参数

    本例将通过location.search来进行字符串拼接成json以及查询域名参数的value console.log(request('id')); function request(obj){ v ...

  5. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

  6. SpringMVC中参数绑定

    SpringMVC中请求参数的接收主要有两种方式, 一种是基于HttpServletRequest对象获取, 另外一种是通过Controller中的形参获取 一  通过HttpServletReque ...

  7. Python初级教程

    Python语言的特点 优点: - 简单 - 易学 - 免费,开源 - 高层语言 - 可移植性(可再多平台运行) - 解释性(不需要编译,可直接运行) - 面向对象 - 可扩展性(缺点:运行效率相对较 ...

  8. Oracle-01:基础命令小结

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 记录一下我的Oracle学习之路,详细的安装教程忙完这俩天会认真总结一版 本次记录这次学习cmd基础命令 一, ...

  9. SSM-Spring-18:Spring中aspectJ的XML版

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- aspectJ的xml版是开发中最常用的: 下面直接已案例入手,毕竟繁琐的日子不多了 案例:两个接口,俩个实现 ...

  10. 可能是迄今为止最好的GitHub代码浏览插件--赞

    https://chrome.google.com/webstore/category/extensions?hl=zh-CN 搜索"insight.io" chrome://ex ...