目录

观察者模式(Observer)

理解

UML图

优缺点

观察者模式在各语言中的支持

Java

C#

实例

小丑表演

办公室摸鱼

投资者与股票


观察者模式(Observer)

本质:触发联动

目标对象变化时,会通知所有登记的观察者对象行动。

别名:

发布-订阅(Publish/Subscribe)模式
模型-视图(Model/View)模式
源-监听器(Source/Listener)模式
从属者(Dependents)模式。

理解

  • 是一对多的单向依赖:多个观察者对象同时观察一个目标对象, 观察者依赖于目标。
  • 相互观察时注意死循环
    • 若 A、B观察C,B、C观察A,则需要两套观察模式,否则死循环
  • 通知的顺序:同时
    • 多个观察者是平行的(虽然是循环,但几乎同时完成)

减少对象之间的耦合有利于系统的复用,但同时需要使这些低耦合度的对象行动协调一致(观察者对象行动的方法要保持参数一致)

UML图:

Subject:抽象被观察者(目标)

  • 一个目标可以被多个观察者观察。目标变化时,目标会通知所有登记的观察者
  • 拥有一个抽象观察者的引用

Observer:抽象观察者

  • 得到目标的通知时更新自己。更新方法,图上Updata()

ConcreteSubject:具体被观察者

  • 将状态存入具体现察者对象。自己变化时,给所有登记的观察者发出通知

ConcreteObserver:具体观察者

  • 拥有一个指向具体目标的引用

优缺点

优点:

  • 实现了观察者和被观察者之间的抽象耦合。
  • 动态联动
  • 广播通信。被观察者会向所有的登记的观察者发出通知。

缺点:

可能会引起无谓的操作。

由于采用广播方式,不管观察者需不需要,每个观察者都会被调用update方法

观察者模式在各语言中的支持

Java

1.Observer接口
Observer为java.util包下的一个接口,源码如下:

public interface Observer {void update(Observable o, Object arg);
}

该接口约定了观察者的行为

所有观察者需要在被观察对象发生变化时做出反应,所做的具体反应就是实现Observer接口的update方法。

  • 当前接口代表观察者,要与被观察对象交互,需要持有被观察对象Observable的引用,因此update方法一个参数的类型是Observable
  • 与调用者通信,则是使用Object类型的参数。该参数是调用者调用Observable实例的notifyObservers(Object obj)方法时传入的,也可以不传。

第一个参数是为观察者提供了一种拉取数据的方式,update中的业务可以根据所需去拉自己想要的被观察对象的信息(一般被观察对象中提供getter),第二个参数则是由调用者调用notifyObservers(Object obj)将一些信息推过来。通过这两个参数,观察者,被观察对象,调用者(调用通知刷新方法的可能是被观察对象本身,此时只存在观察者与被观察者两者)三者就联系起来了。

2.Observable类
java.util.Observable

该类实现了被观察者的功能

该类的成员变量和方法如下:

public class Observable {private boolean changed = false;private Vector<Observer> obs;public Observable(){};protected synchronized void setChanged(){};protected synchronized void clearChanged(){};public synchronized void addObserver(Observer o){};public synchronized void deleteObserver(Observer o) {};public synchronized void deleteObservers(){};public synchronized boolean hasChanged(){};public synchronized int countObservers(){};public void notifyObservers(){};public void notifyObservers(Object arg){};
}

C#

.NET中提供了Delegate与Event机制

实例

小丑表演

镇上来了一位小丑,为大家表演节目,所有观看的观众会根据小丑表演的精彩与否来做出相应的反应,比如表演的好就鼓掌喝彩,表演的不好就倒喝彩,表演完毕观众就退场。

分析:

  • 观众是观察者,应该实现Observer接口
  • 小丑是被观察者,应该继承Observable类

观众会根据小丑表演的状态改变自己的行为

package com.test;import java.util.Observable;
import java.util.Observer;//观众类
public class Viewer implements Observer{private int id;public Viewer(int id) {super();this.id = id;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic void update(Observable o, Object arg) {Integer state=(Integer) arg;switch(state) {case Clown.good:applause();break;case Clown.bad:cheerback();break;case Clown.complete:exit();break;}}private void applause() {System.out.println(id+"号观众鼓掌了");}private void cheerback() {System.out.println(id+"号观众喝倒彩");}private void exit() {System.out.println(id+"号观众退场了");}}
package com.test;import java.util.Observable;
import java.util.Random;
//小丑类
public class Clown extends Observable{public static final int good=0;public static final int bad=1;public static final int complete=2;public void perform() {System.out.println("小丑开始表演");//0-2随机值int random=new Random().nextInt(2);switch(random) {case good:System.out.println("小丑表演得好");break;case bad:System.out.println("小丑表演得不好");break;}setChanged();//小丑的状态传给观众的update方法的第二个参数notifyObservers(random);}public void exit() {System.out.println("小丑表演结束");setChanged();//小丑的状态传给观众的update方法的第二个参数notifyObservers(complete);}}
package com.test;public class Test {public static void main(String[] args) {Clown c=new Clown();for(int i=1;i<4;i++) {Viewer v=new Viewer(i);c.addObserver(v);System.out.println(v.getId()+"号观众入席");}c.perform();c.exit();}}

办公室摸鱼

办公时间摸鱼, 在老板到来时,前台负责通知同事进入工作状态

  • 观察者:两个同事,需要实现Observer接口
  • 被观察者有两个:前台和老板,应该继承Observeable类
    • 前台通知:摸鱼的人改为工作状态
    • 老板通知:摸鱼的人被老板发现并且批评

package qiqi.work;import java.util.Observable;public class Boss extends Observable {private int state=0;//离开public void com() {System.out.println("我大老板回来了");state=2;//回来setChanged();//必须要写notifyObservers(state);//发出通知}}
package qiqi.work;import java.util.Observable;public class Secretary extends Observable{private int state=0;//老板离开public void see() {System.out.println("老板回来了");state=1;//老板回来啦setChanged();notifyObservers(state);}}
package qiqi.work;import java.util.Observable;
import java.util.Observer;public abstract class Observers implements Observer{protected String name;public Observers(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic abstract void update(Observable o, Object arg);public abstract void see();public abstract void exit();public abstract void criticize();}
package qiqi.work;import java.util.Observable;
import java.util.Observer;public class NBAObserver extends Observers{public NBAObserver(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void update(Observable o, Object arg) {// TODO Auto-generated method stubInteger state=(Integer)arg;switch(state){case 0:see();break;case 1:exit();break;case 2:criticize();break;//老板通知}}@Overridepublic void see() {// TODO Auto-generated method stubSystem.out.println(name+"看NBA");}@Overridepublic void exit() {// TODO Auto-generated method stubSystem.out.println(name+"停止看NBA,开始工作");}@Overridepublic void criticize() {// TODO Auto-generated method stubSystem.out.println(name+"你居然在工作时间看NBA,快工作!");}}
package qiqi.work;import java.util.Observable;public class StockObserver extends Observers{public StockObserver(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void see() {// TODO Auto-generated method stubSystem.out.println(name+"看股票");}@Overridepublic void exit() {// TODO Auto-generated method stubSystem.out.println(name+"停止看股票,开始工作");}@Overridepublic void criticize() {// TODO Auto-generated method stubSystem.out.println(name+"你居然在工作时间看股票,快工作!");}@Overridepublic void update(Observable o, Object arg) {// TODO Auto-generated method stubInteger state=(Integer)arg;switch(state){case 0:see();break;case 1:exit();break;//秘书通知case 2:criticize();break;//老板通知}}}
package qiqi.work;public class Test {public static void main(String[] args) {NBAObserver nba=new NBAObserver("张三");StockObserver stock=new StockObserver("李四");Secretary s=new Secretary();s.addObserver(nba);s.addObserver(stock);s.see();Boss b=new Boss();b.addObserver(nba);b.addObserver(stock);b.com();}}

投资者与股票

注册的投资者在股票市场发生变化时,可以自动得到通知的功能

当观察者数量无法确定时,可以用一个List来保存观察者

不使用Observer类和接口,代码如下:

package com.invest;//观察者接口
public interface IInvestor {void update(Stock stock);
}
package com.invest;//具体观察者
public class Investor implements IInvestor{private String name;private Stock stock;public Investor(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Stock getStock() {return stock;}public void setStock(Stock stock) {this.stock = stock;}@Overridepublic void update(Stock stock) {System.out.println(name+" "+stock.symbol+" "+stock.price);}}
package com.invest;import java.util.ArrayList;//抽象被观察者
public abstract class Stock {protected String symbol;protected double price;private ArrayList<Investor> investors=new ArrayList<Investor>();public Stock(String symbol, double price) {super();this.symbol = symbol;this.price = price;}public String getSymbol() {return symbol;}public void setSymbol(String symbol) {this.symbol = symbol;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;Notify();//状态改变,触发通知}public void Attach(Investor investor) {investors.add(investor);}public void Detach(Investor investor) {investors.remove(investor);}public void Notify() {for(Investor i:investors)i.update(this);}}
package com.invest;//具体被观察者
public class QQ extends Stock{public QQ(String symbol, double price) {super(symbol, price);// TODO Auto-generated constructor stub}}
package com.invest;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubInvestor i1=new Investor("张三");Investor i2=new Investor("李四");Stock s=new QQ("腾讯",120.1);s.Attach(i1);s.Attach(i2);s.setPrice(120.4);s.setPrice(121.1);s.Detach(i2);s.setPrice(122.2);}}

使用Observer接口和Observerable类,代码如下:

package com.invest1;import java.util.Observable;
import java.util.Observer;//观察者
public class Investor implements Observer{private String name;public Investor(String name) {super();this.name = name;}@Overridepublic void update(Observable o, Object arg) {Integer a=(Integer)arg;if(a==Stock.getState()) System.out.println(name+"买的股票:"+Stock.getSymble()+"价格变为"+Stock.getPrice());}}
package com.invest1;import java.util.Observable;public class Stock extends Observable{private static String symble;private static double price;private static int state=0;//1表示状态变化,0表示不变public Stock(String symble, double price) {super();this.symble = symble;this.price = price;}public static String getSymble() {return symble;}public void setSymble(String symble) {this.symble = symble;}public static double getPrice() {return price;}public void setPrice(double price) {this.price = price;change();//价格改变,被观察者的状态改变}public void change() {setChanged();setState(1);notifyObservers(getState());//1表示状态变化,0表示不变}public static int getState() {return state;}public static void setState(int state) {Stock.state = state;}}
package com.invest1;public class Main {public static void main(String[] args) {Investor i1=new Investor("张三");Investor i2=new Investor("李四");Stock s=new Stock("谷歌",120.1);s.addObserver(i1);s.addObserver(i2);s.setPrice(122.1);}}

23种设计模式——观察者模式相关推荐

  1. 简单易懂23种设计模式——观察者模式【含C++代码实例】

    23种设计模式C++实现--观察者模式 在做面向对象的软件开发时我们往往想达到更高的代码可复用性和更合理的软件颗粒度. 根据<设计模式--可复用面向对象软件的基础>所说:"你必须 ...

  2. 23种设计模式-观察者模式

    观察着模式 观察者模式(有时又被称为模型-视图(View)模式.源-收听者(Listener)模式或从属者模式)是软件设计模式的一种.在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本 ...

  3. 23种设计模式-观察者模式《关二爷成名后的生活》

    对于许久不用的东西,容易忘记.百度许久,也未能找到自己所要. 从今日起,有些东西就记载下来,不仅方便自己,希望能帮到他人吧! 观察者模式(有时又被称为模型-视图(View)模式.源-收听者(Liste ...

  4. 【23种设计模式】观察者模式(Observer Pattern)

    个人主页:金鳞踏雨 个人简介:大家好,我是金鳞,一个初出茅庐的Java小白 目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客:这里是CSD ...

  5. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  6. 从追MM谈23种设计模式

    从追MM谈Java的23种设计模式 1.FACTORY-追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说&quo ...

  7. 【设计模式】Java 23种设计模式对比总结

    一.设计模式的分类 创建型模式,共五种(1-5):工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种(6-12):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...

  8. 23种设计模式C++实现UML+源码汇总

    设计模式-汇总 代码开源仓库地址 23种设计模式C++实现 C++中的开闭原则使用C++多态功能实现附源码 C++基于多态实现依赖颠倒原则附源码 C++ 的静态成员变量为什么一定要在类外定义 23种设 ...

  9. 【java】java开发中的23种设计模式详解

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

最新文章

  1. SAP QM初阶之启用了Multiple Specification功能后检验批的不同之处?
  2. 洛谷P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)
  3. 付力力: 基于 ImpalaS 构建实时用户行为分析引擎
  4. python代码书写_Python代码的优雅写法,让代码更简洁
  5. 中科大 计算机网络6 Internet结构和ISP
  6. selenium java po模式_selenium + java po模式
  7. Linux下的web调度器——squid实现(负载均衡)
  8. JavaWeb — session+Cookie
  9. xargs与cp结合使用
  10. 基于python的猜大小游戏
  11. 一文详解 Http 短轮询、长轮询
  12. leetcode---栈
  13. Markdown (CSDN) MD编辑器(一)- 实现页内跳转
  14. rk3288 定时器使用
  15. 学完Python的7大就业方向,哪个赚钱多?
  16. 光纤布线兵法之特色产品(一)
  17. 2021-12-25 《聪明的投资者》学习笔记-18.对八组公司的比较
  18. vue3 导入svg图片
  19. cadence 原理图不能打印成PDF 解决方案
  20. 李国庆是如何被“踢出”当当的?

热门文章

  1. Mac OS电源管理大解析
  2. table表格基础知识及简单运用
  3. 潮科技有奖问答⑩|云丁科技:2019年智能家居领域你最期待的创新和突破是什么?...
  4. 计算机视觉图像基本处理--Harris角点检测
  5. Download pre-built shared indexes Pre-built maven library shared indexes reduce the indexing time
  6. php fwrite 错误信息,fwrite错误
  7. 计算机登陆用户显示黑屏,win7系统电脑开机输入登录账号密码后出现黑屏的原因分析及两种解决方法...
  8. JavaScript 中的作用域(scope)是指什么?
  9. Linux系统目录结构和相对-绝对路径
  10. throw和throws用法