zoukankan      html  css  js  c++  java
  • 设计模式——观察者模式

    概念

    观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

    观察者模式结构图

    该模式包含四个角色:

    • 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
    • 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
    • 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
    • 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

    代码示例

    下面用一个微信公众号发布文章的列子来简单讲解下观察者模式。通过这个列子,能帮助我们加深对观察者模式的理解。

    step1:定义Subject和Observer接口

    //定义一个微信公众号接口,相当于类图中的Subject角色
    public interface WeChatOfficialAccount {
    
        public void registerObserver(WeChatObserver observer);
        public void removeObserver(WeChatObserver observer);
        public void notifyObserver(String message);
    
    }
    //定义一个微信用户接口,相当于类图中的Observer角色
    public interface WeChatObserver {
    
        void pullArticle(String message);
    
    }
    
    

    step2:编写实现类

    //这步没什么好说的
    public class MyWeChatOfficialAccount implements WeChatOfficialAccount {
    
        private List<WeChatObserver> observerList;
    
        public MyWeChatOfficialAccount(){
            this.observerList = new ArrayList<>();
        }
    
        @Override
        public void registerObserver(WeChatObserver observer) {
            this.observerList.add(observer);
        }
    
        @Override
        public void removeObserver(WeChatObserver observer) {
            this.observerList.remove(observer);
        }
    
        @Override
        public void notifyObserver(String message) {
            observerList.forEach(item->item.pullArticle(message));
        }
    }
    
    public class WeChatUser implements WeChatObserver {
    
        private String userName;
    
        public WeChatUser(String userName){
            this.userName = userName;
        }
    
        @Override
        public void pullArticle(String message) {
            System.out.println(userName+" receive message:"+message);
        }
    
    }
    

    step3:编写客户端类

    public class Main {
    
        public static void main(String[] args) {
            WeChatUser user1 = new WeChatUser("csx-java");
            WeChatUser user2 = new WeChatUser("zr-php");
    
            WeChatOfficialAccount officialAccount = new MyWeChatOfficialAccount();
            //csx和zr两个用户都订阅了这个公众号
            officialAccount.registerObserver(user1);
            officialAccount.registerObserver(user2);
    
            //公众号发布文章,订阅者都会受到文章通知
            officialAccount.notifyObserver("Java is good...");
            //zr取消订阅
            officialAccount.removeObserver(user2);
            //再次发布文章
            officialAccount.notifyObserver("Java is more popular than php");
        }
    }
    

    优缺点

    优点

    • 观察者和被观察者是抽象耦合的(面向接口耦合)。
    • 建立一套通知触发机制。

    缺点

    • 如果需要通知的观察者太多,可能会比较耗时。其中一个观察者通知出问题的话可能会影响其他观察者的通知。

    和生产者消费者模式的区别

    这两种模式比较相似。其实我个人觉得没有太大的必须去纠结两者的区别。如果非要说下两者的区别的话,大概有:

    • 生产者模式中成产者一般不负责通知观察者,只是负责生产消息,然后将消息分发到一个消息队列。
    • 生产者消费者模式一般用于系统和系统之间解耦,而观察者模式一般用于系统内的某些逻辑。(可以参考Spring的ApplicationListener,这是一种金典的观察者模式的使用。)

    参考

  • 相关阅读:
    MySQL7:性能优化
    MySQL6:视图
    MySQL5:触发器
    MySQL4:索引
    MySQL3:存储过程和函数
    MySQL1:MySQL函数汇总
    MySQL2:四种MySQL存储引擎
    Spring7:基于注解的Spring MVC(下篇)
    Spring6:基于注解的Spring MVC(上篇)
    Linux查看端口号
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/12516569.html
Copyright © 2011-2022 走看看