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系统,能够应对变化)
原文地址:https://www.cnblogs.com/Shock-W/p/9316250.html