zoukankan      html  css  js  c++  java
  • Head First设计模式之观察者(Observer)模式(二)

                        小白将从以下几点对观察者模式进行解析

      PS:有趣的事情发生时,可千万不要错误^_^

    • 观察者模式引入的设计技巧

    • 观察者模式的定义及类图

    • 观察者模式的优缺点

    • 观察者模式的应用场景

    • 观察者模式实战

    • 总结

    零、观察者模式引入的技巧

      先过一遍,放入脑海中,等看完后面所有的内容,可以结合上下文进行消化

      我们要做的不是看过、读过、理解过、消化过,而是需要将其平常化,使用模式就像使用变量一样简单。

    1. 为了交互对象之间的松耦合设计而努力(松耦合的设计能够让我们建立有弹性的OO系统,能够应对变化)

     

    一、观察者模式的定义及类图

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

      类图:类图中一共有四个角色,主题、观察者、具体主题、具体观察者

    1.   主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法。
    2.   观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。
    3.   具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。
    4.   具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。

      以下是UML类图

      

     

     

    二、策略模式的优缺点

      优点:

      1. 解除耦合,让耦合的双方都依赖于抽象,从而使各自的变化不会影响到另一边(除设计上的变化外)

      缺点:

          1. 如果观察者的对象非常多时,通知到所有的观察者所花费的时间会比较多,有可能还没通知完,被观察者的状态又发生变化了,其实看到这,你会联想到MQ 消息队列,观察者的push 模式可以参考MQ (好好思考下

          2. 如果观察者和被观察者之间存在循环依赖关系的话,将会导致系统奔溃

          3.观察者可以随时知道被观察者对象发生了变化,但是观察者模式不知道被观察者对象是如何发生变化的,当然不关系就没有什么问题

     三、策略模式的应用场景

    1. 配置中心, 相信这个都不陌生, 当配置发现变更时,所有监听的客户端都能拿到最新的配置。配置中心  可以做成pull 模式 或者 push 模式
    2. 报纸订阅服务,现实生活中,只要你订阅了报纸,那么报社每次出版新报纸,就会送到你家门口

    四、策略模式实战

      以下代码不会太复杂,只是作为示例,我这边以配置中心来进行实战

      主题(Subject)角色设计如下:

      

    /**
     * @Author: wander
     * @Descripttion:
     * @Date: 2018年07月17日09时49分
     */
    public interface Subject {
    
        void addObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObservers();
    
    }

      

      观察者(Observer)角色设计如下:

    /**
     * @Author: wander
     * @Descripttion:
     * @Date: 2018年07月17日09时46分
     */
    public interface Observer {
    
        void update(String config);
    
    }

       

      具体观察者 activity 设计 如下:

    /**
     * @Author: wander
     * @Descripttion: 活动项目观察者
     * @Date: 2018年07月17日09时52分
     */
    public class ActivityObserver implements Observer {
    
        @Override
        public void update(String config) {
            System.out.println("activity 项目接收到了新配置:" + config);
        }
    }

      

      具体观察者 cms 设计 如下:

    /**
     * @Author: wander
     * @Descripttion:
     * @Date: 2018年07月17日09时53分
     */
    public class CmsObserver implements Observer {
    
        @Override
        public void update(String config) {
            System.out.println("cms 项目接收到了新配置:" + config);
        }
    }

      

       配置主题设计如下:

      

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author: wander
     * @Descripttion: 配置 主题
     * @Date: 2018年07月17日09时54分
     */
    public class ConfigSubject implements Subject{
    
        private List<Observer> observers = new ArrayList<>();
    
        private String config = "哈哈哈";
    
        @Override
        public void addObserver(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            if (observers.size() <= 0) return;
            observers.remove(observer);
        }
    
        @Override
        public void notifyObservers() {
            observers.forEach(observer -> observer.update(config));
        }
    
        public void setConfig(String config) {
            this.config = config;
        }
    }

      

      运行环境设计如下:

      

    /**
     * @Author: wander
     * @Descripttion:
     * @Date: 2018年07月17日09时59分
     */
    public class Main {
    
        public static void main(String[] args) {
            //新建配置主题
            ConfigSubject subject = new ConfigSubject();
    
            //创建观察者 并 监听配置主题
            Observer activity = new ActivityObserver();
            Observer cms = new CmsObserver();
    
            subject.addObserver(activity);
            subject.addObserver(cms);
    
            //配置主题 更新 消息了 通知所有的 观察者
            subject.setConfig("windows default");
            subject.notifyObservers();
    
        }
    
    }

      

      运行结果如下:

        

    activity 项目接收到了新配置:windows default
    cms 项目接收到了新配置:windows default

    五、总结

      观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者所知道。

    目前一共积累了4种设计技巧

    1.  封装变化(把会变化的部分取出并“封装”起来,好让其他部分不会受到影响,这样一来,代码变化引起的不经意后果变少,系统变得更有弹性

    2. 针对接口编程,而不是针对实现编程(可以把具体的实现延迟到”运行时“,执行时会根据实际状况执行到真正的行为,不会在编译时直接绑死,充分利用多态使系统更有弹性

    3. 多用组合,少用继承("有一个”可能比“是一个”更好,可以在“运行时”动态的改变具体的实现,这样使系统有很大的弹性)

    4. 为了交互对象之间的松耦合设计而努力(松耦合的设计能够让我们建立有弹性的OO系统,能够应对变化)
  • 相关阅读:
    CentOS VPS
    Make 命令教程
    Nginx 学习
    字体对齐问题
    postman curl
    linux命令
    服务器
    操作系统
    nginx-1.15遇到无法加载php文件报404的问题
    thinkphp6.0框架下载与安装
  • 原文地址:https://www.cnblogs.com/Shock-W/p/9316250.html
Copyright © 2011-2022 走看看