观察者模式

作者:某人_Valar
如需转载请保留原文链接;

设计模式的3大类:

  • 创建型模式(5种)建造者模式,单例模式,工厂方法模式,抽象工厂模式,原型模式。
  • 结构性模式(7种)适配器模式,装饰模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
  • 行为型模式(11种)策略模式,模板方法模式,观察者模式,迭代器模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。

1. 什么是观察者模式

观察者模式又被称为发布-订阅模式,属于行为型设计模式中的一种。

观察者模式就像报纸的订阅。

  • 1 报社的业务就是出版报纸
  • 2 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他么的订户,就会一直收到报纸。
  • 3 当你不想再看报纸的时候,取消订阅,他们就不会再送报纸来。
  • 4 只要报社还在运营,就会一直有人向他们订阅报纸或者取消订阅。

在观察者模式中出版者被称为“主题(Subject)”,订阅者称为“观察者(Observer)”

定义:观察者模式定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

  • 对于观察者模式,主题只知道观察者实现了某个接口(也就是Observer接口)。主题不需要知道观察者的具体类是谁,做了什么或其他细节。
  • 任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加,删除观察者。
  • 当我们有新的具体类需要成为观察者,我们不需要修改主题的代码,在新的类里实现观察者接口,然后注册成为观察者即可。

2. 观察者模式的实现

拿微信公众号系统来说,公众号是Subject,订阅的用户是Observer,当公众号更新时就会通知这些用户。

(1)观察者接口

所有的观察者都必须实现观察者接口,其里面定义的update方法会在主题状态改变时调用。

public interface Observer {
    public void update(String message);
}
(2)具体观察者
public class WeixinUser implements Observer {
    //微信用户名
    private String name;
    public WeixinUser(String name){
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println(name+" -- "+message);
    }
}
(3)被观察者(主题)接口
public interface Subject {
    //增加订阅者
    public void attach(Observer observer);
    //删除订阅者
    public void detach(Observer observer);
    //通知订阅者更新消息
    public void notify(String message);
}
(4)具体的被观察者(主题)

在这个例子中,微信公众号是Subject(主题),其需要实现主题接口里面的方法,另外还需要存储订阅了此公众号的微信用户。

public class SubscriptionSubject implements Subject {
    //存储订阅公众号的微信用户
    private List<Observer> weixinUserList = new ArrayList<>();
    @Override
    public void attach(Observer observer) {
        weixinUserList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        weixinUserList.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer: weixinUserList) {
            observer.update(message);
        }
    }
}
(5)测试
public class Test {
    public static void main(String[] args){
        SubscriptionSubject mSubject = new SubscriptionSubject();
        //创建微信用户
        WeixinUser user1 = new WeixinUser("鲁班大师");
        WeixinUser user2 = new WeixinUser("程咬金");
        WeixinUser user3 = new WeixinUser("宫本武藏");
        //订阅公众号
        mSubject.attach(user1);
        mSubject.attach(user2);
        mSubject.attach(user3);
        //公众号更新发出新的消息给订阅的用户
        mSubject.notify("敌军还有30秒到达战场");
    }
}

运行结果


控制台结果

3. 使用观察者模式的场景以及优缺点

使用场景:

  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

优点:

  • 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,易于扩展。
  • 方便形成一条触发链,可以依次对各个观察者的方法进行处理。

缺点:

  • 由于是链式触发,当观察者比较多的时候,需要注意性能问题。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

松耦合(观察者模式是松耦合的一种实现方式):
当两个对象之间松耦合,他们依然可以交互,但是不太清除彼此的细节。

参考:

《Head First设计模式》
《Android进阶之光》
观察者模式-w3cschool
观察者模式-菜鸟教程

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

推荐阅读更多精彩内容