特别说明:本篇博客来自于设计模式菜鸟教程

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

实现

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

步骤 1

创建 Subject 类。

Subject.java

import java.util.ArrayList;
import java.util.List;public class Subject {private List<Observer> observers = new ArrayList<Observer>();private int state;public int getState() {return state;}public void setState(int state) {this.state = state;notifyAllObservers();}public void attach(Observer observer){observers.add(observer);        }public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}}
}

步骤 2

创建 Observer 类。

Observer.java

public abstract class Observer {protected Subject subject;public abstract void update();
}

步骤 3

创建实体观察者类。

BinaryObserver.java

public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); }
}

OctalObserver.java

public class OctalObserver extends Observer{public OctalObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); }
}

HexaObserver.java

public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); }
}

步骤 4

使用 Subject 和实体观察者对象。

ObserverPatternDemo.java

public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new Subject();new HexaObserver(subject);new OctalObserver(subject);new BinaryObserver(subject);System.out.println("First state change: 15");    subject.setState(15);System.out.println("Second state change: 10");    subject.setState(10);}
}

步骤 5

验证输出。

First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
1 篇笔记
  1. fatcheung

    134***7025@qq.com

    观察者模式,我理解的就是观察者订阅被观察者的状态,当被观察者状态改变的时候会通知所有订阅的观察者的过程。所以以下这种写法会不会更加容易理解一些呢?

    观察者接口:

    public abstract class Observer {    public abstract void update(String msg);
    }

    第一个观察者:

    public class F_Observer extends Observer {public void update(String msg) {System.out.println(F_Observer.class.getName() + " : " + msg);}
    }

    第二个观察者:

    public class S_Observer extends Observer {public void update(String msg) {System.out.println(S_Observer.class.getName() + " : " + msg);}
    }

    第三个观察者:

    public class T_Observer extends Observer {public void update(String msg) {System.out.println(T_Observer.class.getName() + " : " + msg);}
    }

    被观察者:

    public class Subject {        private List<Observer> observers = new ArrayList<>();    //状态改变    public void setMsg(String msg) {        notifyAll(msg);    }   //订阅    public void addAttach(Observer observer) {        observers.add(observer);    }    //通知所有订阅的观察者    private void notifyAll(String msg) {        for (Observer observer : observers) {            observer.update(msg);        }   }
    }

    使用方法:

    public class Main {    public static void main(String[] args) {        F_Observer fObserver = new F_Observer();        S_Observer sObserver = new S_Observer();        T_Observer tObserver = new T_Observer();                Subject subject = new Subject();        subject.addAttach(fObserver);        subject.addAttach(sObserver);        subject.addAttach(tObserver);                subject.setMsg("msg change");    }
    }

    运行结果: test.F_Observer : msg changetest.S_Observer : msg changetest.T_Observer : msg change

(设计模式十三)java设计模式之观察者模式相关推荐

  1. 【设计模式】Java设计模式 - 享元模式

    [设计模式]Java设计模式 - 享元模式

  2. 【设计模式】Java设计模式 - 模板模式

    [设计模式]Java设计模式 - 模板模式

  3. 【设计模式】Java设计模式 - 适配器模式

    [设计模式]Java设计模式 - 适配器模式

  4. 设计模式:java及spring观察者模式(有利于代码解耦)

    http://www.cnblogs.com/softidea/p/5716870.html 什么是ApplicationContext?  它是Spring的核心,Context我们通常解释为上下文 ...

  5. 【设计模式】Java设计模式 - 中介者模式

    Java设计模式 - 中介者模式

  6. java经典设计模式4,JAVA设计模式(4) 之装饰设计模式

    在现实生活中我们的汽车都具备跑的功能,我们可以不改变汽车原有功能的前提下,把它放入一个装修厂,开进去让里面给咱们的车子做一些装饰,开出来之后呢,就具备了上天的功能了(技术可达是可以的哈),这就给原来的 ...

  7. 【Java设计模式】Java设计模式之(十五)策略模式(Strategy Pattern)

    本文目录 一.策略模式介绍 1.1 含义 1.2 适用场景 1.3 主要解决 1.4 应用实例 1.5 优缺点 二.策略模式实现 2.1 类图 2.2 代码实现 第一个案例:策略模式代码实现 第二个案 ...

  8. 【设计模式】java设计模式之 -- 策略模式

    对于代码中总是会有需要变化的部分和需要固定不变的部分.对于需要变化的部分,一般可以采用继承的方式,让子类对父类的方法进行重写,以改变已有的行为:如果变化的部分并不是所有子类都必须要有的,那就可以采用接 ...

  9. java设计模式adapter,java设计模式-适配器模式(Adapter)

    定义 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 适配器模式的用途 用电器做例子,笔记本电脑的插头一般都是三相的,即除了阳极 ...

  10. 【Java设计模式】Java设计模式之(十九)装饰器模式(Decorator Pattern)

    本文目录 一.装饰器模式介绍 1.1 含义 1.2 适用场景 1.3 主要解决 1.4 应用实例 1.5 优缺点

最新文章

  1. 【React Native】iOS原生导航跳转RN页面
  2. Golang微服务开发实践
  3. 皮一皮:被看穿的既视感...
  4. wince下的蓝牙串口通信
  5. 一些恶心的代码片段,你看了就知道!
  6. spark Docker镜像构建及push脚本
  7. MULE ESB环境搭建和例子(通过装插件的方式)
  8. 当随机不够随机:一个在线扑克游戏的教训
  9. fis 详细介绍(mac版) - 12-26没有弄完 - 暂停
  10. 流露人间的情回忆儿童节
  11. Java基础学习 -- I/O系统、流
  12. Centos+Mysql+sphinx+mmseg(rhel4)
  13. ListT to DataTable
  14. 2018 CSS 大会多图见闻录
  15. Flexsim——初学AGV必看的知识点(如何解决AGV在不同区域speed不同)
  16. java 把客户信息录入数组,需求说明 java-实现添加客户信息 客户信息包括:姓名、年龄、是否有会员卡...
  17. php随机发牌游戏,JavaScript_javascript实例--教你实现扑克牌洗牌功能,我们一般都会按照顺序把随机 - phpStudy...
  18. 旭日X3派,从零到TogetherRos的快速体验
  19. 【数据可视化应用】IDW插值计算实战案例(附Python和R语言代码)
  20. iOS开发第三方大全

热门文章

  1. Windows 各个版本 TortoiseSVN 下载
  2. vue elementui 年份列表和月份列表
  3. 蓝牙设备的连接与配对
  4. 将 DTS 用于业务智能解决方案的最佳实践
  5. 扫描探针显微术入门(1)
  6. 睡觉,吃饭,打豆豆,任务一
  7. 三阶魔方复原简易方法笔记
  8. powermill程序单html模板,3-PowerMill程序单的模板定制
  9. 《S5PV210三星原厂开发板使用说明+完整原理图》
  10. javascript做的一个根据table中某个td的值为日期时的倒计时