Observer模式即观察者模式,该模式中,被观察者的状态发生变化后会通知给观察者。

此模式适用于根据对象状态进行处理的场景。

示例程序

下面代码的功能是:被观察者是一个随机数生成器,有两个观察者,分别以数值形式和图示形式展示被观察者生成的数字。

程序类图

程序

抽象的数字生成器

public abstract class NumberGenerator {
//观察者列表
private ArrayList observers = new ArrayList();
//增加观察者
public void addObserver(Observer observer) {
observers.add(observer);
}
//删除观察者
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
//提醒观察者
public void notifyObservers() {
Iterator it = observers.iterator();
while (it.hasNext()) {
Observer o = (Observer)it.next();
o.update(this);
}
}
public abstract int getNumber();
public abstract void execute();
}

具体的数字生成器

执行execute()方法后通知观察者

public class RandomNumberGenerator extends NumberGenerator {
private Random random = new Random();
private int number;
public int getNumber() {
return number;
}
public void execute() {
for (int i = 0; i < 20; i++) {
number = random.nextInt(50);
notifyObservers();
}
}
}

观察者接口

public interface Observer {
void update(NumberGenerator generator);
}

观察者(数字形式展示)

public class DigitObserver implements Observer {
public void update(NumberGenerator generator) {
System.out.println("DigitObserver:" + generator.getNumber());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}

观察者(图形方式展示)

public class GraphObserver implements Observer {
public void update(NumberGenerator generator) {
System.out.print("GraphObserver:");
int count = generator.getNumber();
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println("");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}

执行

public class Main {
public static void main(String[] args) {
NumberGenerator generator = new RandomNumberGenerator();
Observer observer1 = new DigitObserver();
Observer observer2 = new GraphObserver();
generator.addObserver(observer1);
generator.addObserver(observer2);
generator.execute();
}
} //结果
DigitObserver:22
GraphObserver:**********************
DigitObserver:11
GraphObserver:***********
DigitObserver:40
GraphObserver:****************************************
DigitObserver:39
GraphObserver:***************************************
DigitObserver:28
GraphObserver:****************************
DigitObserver:23
GraphObserver:***********************
DigitObserver:38
GraphObserver:**************************************
DigitObserver:39
GraphObserver:***************************************
......省略

角色和类图

角色

  • Subject:被观察者

被观察者内部维护了一个观察者的list,定义了增加和删除观察者的方法。同时还定义了一个通知观察者的方法,作用是:如果自己内部发生了变化,通知观察者取得这些变化。本例中由NumberGenerator扮演这个角色。

  • ConcreteSubject:具体的被观察者

实现了被观察者的执行方法,在执行过程中调用方法通知观察者。本例中由RandomNumberGenerator扮演此角色。

  • Observer:观察者

声明供被观察者调用的方法,此方法可以获得被观察者状态的变化值。本例中由Observer接口扮演此角色。

  • ConcreteObserver:具体的观察者

实现了观察者接口的方法,通过这个方法可以获得被观察者的值,达到监控的目的。本例中由DigitObserverGraphObserver扮演此角色。

类图

思路拓展

可复用性

对于具体的被观察者和观察者而言,他们之间的关系由他们的父类和接口进行关联。

具体的被观察者RandomNumberGenerator不需要知道观察者是谁,有多少,它只负责执行时调用通知方法通知观察者即可。

具体的观察者GraphObserverDigitObserver不需要知道是谁实现了NumberGenerator,只负责拿到值并处理即可。

这样的设计降低了耦合度,提升组件可复用性。其做法的特点是:

利用抽象类和接口从具体类中抽出抽象方法。

将实例作为参数传递至类中,或者在类的字段中保存实例时,不使用具体类型,而是使用抽象类型和接口。

Observer的顺序

如果观察者能够改变被观察者的数据,那就要注意观察者的调用顺序了。还要注意防止循环调用

当Subject发生变化时,通知Observer,Observer改变Subject,Subject发生变化,通知Observer...

MVC模式

Model发生改变时通知View,View根据Model的值显示新的内容。Model就是被观察者,View就是观察者。

《图解设计模式》读书笔记8-1 Observer模式的更多相关文章

  1. HeadFirst设计模式读书笔记(3)-装饰者模式(Decorator Pattern)

    装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...

  2. HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern)

    观察者模式:定义了对象之间一对多的依赖关系,这样一来,当一个对象的状态发生改变时,它的依赖者将会受到通知并且自动更新. 有一个模式可以帮你的对象知悉现况,不会错过该对象感兴趣的事,对象甚至在运行时可以 ...

  3. HeadFirst设计模式读书笔记--目录

    HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...

  4. Head First 设计模式读书笔记(1)-策略模式

    一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...

  5. JavaScript设计模式:读书笔记(未完)

    该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...

  6. Head First设计模式读书笔记

    阅读指南: 精读一章内容,手工输入一章代码(注1),与书中描述的思想进行印证,实在搞不懂就放过吧.设计模式绝对不会一次就看懂的. 这本书对于理解设计模式很有帮助,就是例子不太符合中国人的思维模式,但是 ...

  7. 图解http读书笔记

    以前对HTTP协议一知半解,一直不清楚前端需要对于HTTP了解到什么程度,知道接触的东西多了,对于性能优化.服务端的配合和学习中也渐渐了解到了HTTP基础的重要性,看了一些大神对HTTP书籍的推荐,也 ...

  8. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  9. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  10. Java设计模式学习笔记(四) 抽象工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...

随机推荐

  1. spring security OAuth2.0之客户端Client的实现

    项目代码:https://github.com/hankuikuide/microservice-spring-security-oauth2 网上多数的项目客户端都是采用纯js写,或用postman ...

  2. python学习笔记(2):科学计算及数据可视化入门

    一.NumPy 1.NumPy:Numberical Python 2.高性能科学计算和数据分析的基础包 3.ndarray,多维数组(矩阵),具有矢量运算的能力,快速.节省空间 (1)ndarray ...

  3. C# 同比缩放图片

    /** * 无损缩放图片 * bitmap 需要缩放的图片 * w 需要缩放的宽度 * h 需要缩放的高度 * */ public static System.Drawing.Bitmap TBSca ...

  4. 代理层Nginx限流(降级)预案

    典型服务架构介绍 预案适用场景 监控指标 操作手册 相关文档 操作方法 配置语法 配置样例 配置解释 注意事项 典型服务架构介绍 典型的互联网服务访问链路都是分层结构的,从流量入口,到应用层,到后端资 ...

  5. 10年前文章_mpc8313的ltib安装以及u-boot重新编译

    Linux系统下安装ltib(linux target image builder): 1.       下载光盘到本地 wget http://192.168.1.4/share/vendor/mp ...

  6. shell脚本中oldIFS=$IFS

    https://blog.csdn.net/champwang/article/details/54670293 转自https://man.linuxde.net/shell-script/shel ...

  7. JVM 程序计数器

    程序计数器是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转 ...

  8. C\C++下获取系统进程或线程ID(转)

    在程序开发时有时需要获取线程和进程ID以分析程序运行 ()windows下获取进程或线程ID 通过调用系统提供的GetCurProcessId或GetNowThreadID来获取当前程序代码运行时的进 ...

  9. Kettle整理

    下载kettle版本 (1)hadoop version 查看hadoop的版本    hadoop2.6 (2)则在data-integration\plugins\pentaho-big-data ...

  10. sql中的group_concat用法

    group_concat(),手册上说明:该函数返回带有来自一个组的连接的非NULL值的字符串结果.比较抽象,难以理解. 通俗点理解,其实是这样的:group_concat()会计算哪些行属于同一组, ...