定义:

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

结构:(书中图,侵删)

一个抽象的观察者接口,拥有一个更新方法
若干个具体的观察者类
一个抽象的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. 第二次作业 单例模式的SessionFactory

    一.基础Hibernate环境搭建(参见http://www.cnblogs.com/sangewuxie/p/9004968.html) 二.实体类User及User.hbm.xml配置 1.Use ...

  2. C#之Redis所欲为

    一 Redis是一种支持多种数据结构的键值对数据库 1.1Redis下载地址 :https://github.com/MicrosoftArchive/Redis 建议下载 .msi结尾的应用程序进行 ...

  3. ELK 架构之 Logstash 和 Filebeat 安装配置

    上一篇:ELK 架构之 Elasticsearch 和 Kibana 安装配置 阅读目录: 1. 环境准备 2. 安装 Logstash 3. 配置 Logstash 4. Logstash 采集的日 ...

  4. File文件操作学习总结

    1.java.io.file用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录, 2.File类只能用于表示文件(目录)的信息(名称和大小),不能对文件内容进行访问. ...

  5. Boyer-Moore(BM)算法,文本查找,字符串匹配问题

    KMP算法的时间复杂度是O(m + n),而Boyer-Moore算法的时间复杂度是O(n/m).文本查找中“ctrl + f”一般就是采用的BM算法. Boyer-Moore算法的关键点: 从右遍历 ...

  6. 使用非阻塞ServerSocketChannel、SocketChannel代替ServerSocket和Socket

    http://blog.csdn.net/timliang18601860/article/details/7104485

  7. c++ 输出精度

    1  保留小数点后**位 cout.flags(ios::fixed); cout.precision(4); //设置输出精度,

  8. 关于Linux虚拟化技术KVM的科普

    虚拟化技术应用越来越广泛,虚拟化技术需求越来越强劲.KVM.XEN.Docker等比较热门,尤其是KVM技术越来越受欢迎. 基于此背景,了解一下KVM+QEMU就有点必要了. 从网上收集了一些资料进行 ...

  9. 找不到 blog.csdn.net 的服务器 DNS 地址

    找不到 blog.csdn.net 的服务器 DNS 地址 csdn的博客用win7的电脑打不开是怎么回事?手机可以正常打开,csdn的bbs 下载什么的都可以正常使用. blog.csdn.net显 ...

  10. mac升级到php7

    使用homebrew安装php7 brew update #更新源 brew search php #查找源中的php,发现有php7.1版本,安装最新的php7.1 brew install php ...