设计模式之观察者模式

观察者模式的本质:(触发联动)
当修改目标状态时就会触发相应的通知,然后会循环调用所有注册的观察者对象的相应方法。

观察者模式的应用场景:天气预报,许多网站,人等需要第一时间得知天气的变化,然后做各自的出行计划

定义:定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
(一个目标类,多个观察者(用来观察目标)当目标类发生变化时,可以通知到他的所有观察者。)统一通知,各自处理

原理:利用回调函数机制。 所有“观察者类”继承一个“接口”(如Observer),该接口中有一个方法(如,update())。将所有的观察者增添到“目标类”的“链表”中,当目标类的状态发生改变时,目标类可以遍历链表中的所有观察者,调用其update通知到所有的观察者。

image.png

Subject : 观察源事物,可添加或删除自身观察者
Observer : 观察者,可接受事物的通知
当事物发生更新变动,则通知观察者做相应处理,另事物状态与观察者状态保持一致

image.png

目标与观察者之间的关系
(1)事物与观察者的关系,可以是一对多,也可能是多对多
(2)观察者依赖于目标事物,反向则不行
(3)事物类的命名应以Subject结尾,观察者对象则以Oberserver结尾
(4)为了让观察者与事物状态保持一致,应当在事物状态更新后再通知观察者
(5)事物通知多个观察者的顺序是平行的,没有先后之分
(6)执行流程:创建事物 -> 注册观察者 -> 更新事物 -> 通知观察者

image.png
image.png

实现的两种方式:推模型和拉模型

推模型:目标对象主动向观察者推送目标的详细信息推送的信息通常是目标对象的全部或部分数据(相当于广播通信)
拉模型:目标对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。(主动请求)
一般这种模型的实现中,会把目标对象自身通过 update 方法传递给观察者

两种模型比较:
推模型:假定目标对象知道观察者需要的数据(按需分配,复用性差 )
拉模型:目标对象不知道观察者具体需要什么数据,因此把自身传给观察者,由观察者来取值。复用性好。
拉模型下,update 方法的参数是目标对象本身,基本上可以适应各种情况的需要。

利用Java提供的观察者实现
JDK中提供了观察者模式实现的接口:
事物类可继承 java.util.Observable 类作为 被观察对象,此类对状态更新设置更精确,更安全
观察者类可实现 java.util.Observer 接口 作为观察者对象

Observable类对notifyObservers()方法进行了重载,即notifyObservers()与notifyObservers(Object arg).
前者用于拉模型,后者用于推模型。

目标类代码
/**
 * 目标类,继承Observable类,使其成为 可观察的目标类 
 */
public class WeatherSubject extends Observable{
private String weatherState;
public String getWeatherState(){
    return weatherState;
}

public void setWeatherState(String weatherState){
    this.weatherState = weatherState;
    this.setChanged(); //通知之前必须要调用该方法,否则无法通知
    this.notifyObservers("参数");//通知所有的观察者。不管这里传不传参数,都会传给观察者Observable引用。
  }
}

观察者代码
/**
 * 观察者类,实现Observer接口,成为观察者
 */
public class WeatherObserver implements Observer{
private String name;//随便定义一个变量,作为观察者的名字

public WeatherObserver(String name){
    this.name=name;
}

/**
 * Observer接口中的方法,Observable目标类会回调该方法
 * @param observable 目标类的引用,需要进行强制类型转换 //不管通知传不传参数,都会传给观察者Observable引用。
 * @param object 目标类主动传来的对象。 如果目标类的通知没传参数,则object为空
 */
@Override
public void update(Observable observable, Object object){
    System.out.println(name+"收到通知,推送值为"+object+",天气为"+((WeatherSubject)observable).getWeatherState());
   }
}

观察者优缺点?

优点:
1,观察者模式实现了观察者和目标之间的抽象耦合;
2,观察者模式实现了动态联动
3,观察者模式支持广播通信

缺点:
可能会引起无谓的操作---->引起误更新

何时使用观察者模式?(触发联动)

①当一个抽象模型有两个方面,其中一个方面的操作依赖于另外一个方面的状态的变化。
②如果更改一个对象的时候,需要同时连带更改其他对象,而且不知道究竟有多少对象要被连带改变。
③当一个对象必须通知其他对象,但是又不希望这个对象和其他被通知的对象是松散耦合的,也就是说这个对象不想知道具体被通知的对象;
以上三种情况可以考虑观察者模式。

区别对待的观察者模型
场景:
张三希望只接收下雨天的天气预报
李四希望只接收下雨/下雪天的天气预报。
需要根据不同的天气情况,区别对待通知不同的观察者

区别对待的观察者模型中和通用观察者模型的却别在于要根据不同的观察者来进行不同的推送,所以区别在于目标类中的统治方法需要在具体的目标类中进行实现。(因为需要根据不同的情况进行更新,所以需要在具体的目标类中实现刚刚那个方法)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容