观察者模式

作者: 某人_Valar | 来源:发表于2018-02-28 16:15 被阅读52次

    作者:某人_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
    观察者模式-菜鸟教程

    相关文章

      网友评论

        本文标题:观察者模式

        本文链接:https://www.haomeiwen.com/subject/rmwbxftx.html