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. Qt读写Json

    Qt操作Json 1.QJsonDocument 1.详细说明 QJsonDocument类提供了读写JSON文档的方法. QJsonDocument是一个封装了完整JSON文档的类,可以从基于UTF ...

  2. 007-cobbler+koan自动化重装系统

    一.操作步骤 1.在使用cobbler自动化安装的虚拟机上做以下操作 2.安装epel源(先配置好yum) [root@localhost ~]# yum install epel-release - ...

  3. hdu 1505 单调栈升级版

    #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #defin ...

  4. 1130. Infix Expression (25)

    Given a syntax tree (binary), you are supposed to output the corresponding infix expression, with pa ...

  5. java 分页对象以及数据库分页查询

    import java.util.List; public class Pager<T> { private Integer pageSize; private Integer total ...

  6. 2019年8月12日~8月18日 第七周JAVA学习总结

    本周主要完成了PTA代码编写的任务,将报告也完成了,但是由于同学聚会比较多所以JAVA的学习比较少,也没有学习统一建模语言.用在编程的时间平均每天5个小时,用在JAVA学习上平均每天1个小时,用在解决 ...

  7. 【bzoj1336/1337/2823】最小圆覆盖

    题目描述: 给出平面上N个点,请求出一个半径最小的圆覆盖住所有的点 输入: 第一行给出数字N,现在N行,每行两个实数x,y表示其坐标. 输出: 输出最小半径,输出保留三位小数. 样例输入: 4 1 0 ...

  8. 【bzoj4136】[FJOI2015]带子串包含约束LCS问题

    题目描述: 带有子串包含约束的最长公共子序列问题可以具体表述如下. 给定2个长度分别为n和m的序列X和Y,以及一个子串包含约束集S. S中共有k个字符串S={S1,S2,…,Sk},其中字符串Si的长 ...

  9. Oracle Select语句

    Oracle Select语句 作者:初生不惑 Oracle基础 评论:0 条 Oracle技术QQ群:175248146 在本教程中,将学习如何使用Oracle SELECT语句从单个表中查询数据. ...

  10. 正则表达式小结,数据预处理中常用的shell命令

    数据预处理中,这部分命令非常有用. 不需要编写代码,直接通过shell脚本通常就能修改文件格式.有时候sed和awk联合几乎能实现所有功能. 管道命令 | 重定向命令>,2>,>&g ...