1 基础知识

定义:定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖(观察者)都会收到通知并更新。

本质:触发联动

使用场景:关联行为场景,建立一套触发机制。

(1)当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化那么就可以选用观察者模式,将这两者封装成观察者和目标对象,当目标对象变化的时候,依赖于它的观察者对象也会发生相应的变化。这样就把抽象模型的这两个方面分离开了,使得它们可以独立地改变和复用。

(2)如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变,这种情况可以选用观察者模式,被更改的那一个对象很明显就相当于是目标对象,而需要连带修改的多个其他对象,就作为多个观察者对象了

(3)当一个对象必须通知其他的对象,但是你又希望这个对象和其他被它通知的对象是松散耦合的。也就是说这个对象其实不想知道具体被通知的对象。这种情况可以选用观察者模式,这个对象就相当于是目标对象,而被它通知的对象就是观察

者对象了

优点:观察者和被观察者之间建立一个抽象的耦合;支持广播通信。缺点:观察者之间有过多的细节依赖、提高时间消耗及程序复杂度;要避免循环调用。

2 代码示例

使用场景: 观察者查看一个生成数值的对象,并将其结果显示。不过,不同的观察者显示的方式也不同。

Observer接口:

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

生成数值的抽象类:NumberGenerator

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);
}
//向observer发送通知
public void notifyObservers(){
Iterator it = observers.iterator();
while (it.hasNext()){
//调用每个观察者的update方法
Observer o = (Observer)it.next();
o.update(this);
}
}
//获取数值
public abstract int getNumber();
//生成数值
public abstract void execute();
}

子类,生成随机数:RandomNumberGenerator

public class RandomNumberGenerator extends NumberGenerator{

    //随机数生成器
private Random random = new Random();
//当前数值
private int number; //产生10个10以内的数字并向观察者发送通知
public void execute(){
for (int i = 0; i < 10; i++) {
number = random.nextInt(10);
//把每次生成的结果通知给观察者
notifyObservers();
}
} //获取当前数值
public int getNumber() {
return number;
}
}

观察者1:DigitObserver  以数字的形式显示观察得到的数值

public class DigitObserver implements Observer{

    public void update(NumberGenerator numberGenerate) {
System.out.println("观察到的数值:"+numberGenerate.getNumber());
}
}

观察者2:GraphObserver  将观察到的数值以***的形式显示出来

public class GraphObserver implements Observer{
public void update(NumberGenerator numberGenerate) {
System.out.println("图像");
int count = numberGenerate.getNumber();
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println();
}
}

应用层:

public class Test {
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();
}
}

 注:其实Java已经为我们提供了 Observer模式了但是java.util. observer接口和java.util. Observable类并不好用。理由很简单,传递给java.util. Observer接口的 Subject y角色必须是java.util. observable类强(或者它的子类型)的。但Java只能单一继承,也就说如果 Subject 角色已经是某个类的子类了,那么它将无法继承java.util. Observable类。

3 源代码中的使用

4 相关模式

(1)观察者模式和状态模式

观察者模式和状态模式是有相似之处的。观察者模式是当目标状态发生改变时,触发并通知观察者,让观察者去执行相应的操作。而状态模式是根据不同的状态,选择不同的实现,这个实现类的主要功能就是针对状态相应地操作,它不像观察者,观察者本身还有很多其他的功能,接收通知并执行相应处理只是观察者的部分功能。当然观察者模式和状态模式是可以结合使用的。观察者模式的重心在触发联动,但是到底决定哪些观察者会被联动,这时就可以采用状态模式来实现了,也可以采用策略模式来进行选择需要联动的观察者。

(2)观察者模式和中介者模式

观察者模式和中介者模式是可以结合使用的。前面的例子中目标都只是简单地通知一下,然后让各个观察者自己去完成更新就结束了。如果观察者和被观察的目标之间的交互关系很复杂,比如,有一个界面,里面有三个下拉列表组件,分别是选择国家、省份州、具体的城市,很明显这是一个三级联动,当你选择一个国家的时候,省份/州应该相应改变数据,省份/州一改变,具体的城市也需要改变。这种情况下,很明显需要相关的状态都联动准备好了,然后再一次性地通知观察者。也就是界面做更新处理,不会仅国家改变一下,省份和城市还没有改就通知界面更新。这种情况就可以使用中介者模式来封装观察者和目标的关系在使用 Swing的小型应用里面,也可以使用中介者模式,比如,把一个界面所有的事件用一个对象来处理,把一个组件触发事件以后,需要操作其他组件的动作都封装到一起,这个对象就是典型的中介者。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0

观察者模式(Observer)---行为型的更多相关文章

  1. 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)

    观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...

  2. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  3. 设计模式18:Observer 观察者模式(行为型模式)

    Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...

  4. 设计模式 笔记 观察者模式 Observer

    //---------------------------15/04/27---------------------------- //Observer 观察者模式----对象行为型模式 /* 1:意 ...

  5. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  6. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  7. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  8. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  9. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  10. 设计模式-观察者模式(Observer Pattern)

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

随机推荐

  1. 使用pycharm开发web——django2.1.5(五)表单和通用视图

    看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,interesting 刘老师这波讲解很到位,告诉你如何编写单例视图的时候忽然告诉你,其实不用这么麻烦,我们有通用视图,那些总是要做相似的 ...

  2. (十五)mybatis 逆向工程

    目录 为什么需要逆向工程 使用方法 如何读懂生成的代码 总结 为什么需要逆向工程 对于数据库中的那么多的表 ,基本的 CRUD 操作 ,以及 mybatis 需要使用的 接口.mapper ,这些工作 ...

  3. MySQL_Utilities工具

    需求    Python 2.6    MySQL Connector/Python 连接器 下载地址:    http://dev.mysql.com/downloads/utilities/   ...

  4. 【KMP】OKR-Periods of Words

    [KMP]OKR-Periods of Words 题目描述 串是有限个小写字符的序列,特别的,一个空序列也可以是一个串.一个串P是串A的前缀,当且仅当存在串B,使得A=PB.如果P≠A并且P不是一个 ...

  5. MQTT协议探究(一)

    1 准备阶段 MQTT客户端:https://www.cnblogs.com/linzhanfly/p/9923577.html WireShark MQTT服务器(iot.eclipse.org) ...

  6. c#学习笔记-string stringBuilder

    string aTest = "abc";//分配固定的内存大小 aTest += "ddd"; //销毁原先的数据再来分配,消耗大 StringBuilder ...

  7. 获取windows进程信息及CListCtrl控件(List Control)练习

    环境:VS2010/MFC/对话框 效果图: 目录: 1.  关于windows进程信息获取 2.  CListCtrl的使用 ------------------------------------ ...

  8. 集合源码阅读——ArrayList

    ArrayList 关键点: >>扩容每次扩容1.5倍 >>modcount的作用 >>ArrayList的父类AbstractList的成员变量 >> ...

  9. JS 实现继承的方法 ES6 and ES5

    继承 ES6 方法  (类的继承) ES6中有一个属性的 extends 语法: ​ • class Father {} ​ • class Son extends Father{} ​ 注意:是子类 ...

  10. 使用百度地图API自动获取地址和经纬度

    先上效果图,这是直接点击获取经纬度和地址的.没有做搜索的功能. 代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...