31. 观察者模式

作者: Next_吴思成 | 来源:发表于2018-07-17 22:42 被阅读43次

定义

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

通俗理解

“敌不动,我不动,敌若动,我先动”,这是《兵法》一个经典的战略,意思是说,在战场上,我们要注意好敌军的动向,根据敌军的动向来指定自己这一方的作战方针,如果敌人不行动,我们就按兵不动,如果敌人行动,我们就需要比敌人更先行动。这一句话后来被毛泽东融合当时在社会斗争情况总结为"敌来我走,敌驻我扰,敌退我追"!这也是根据敌人的行动来执行自己的战略。

类似于这种,根据敌人的行动类改变自己的方针,就是观察者模式最好的诠释。当敌人行动的时候,他的状态改变了,那么也会影响到我军的状态。当然,在观察者模式当中,定义的是一对多的依赖关系,这在生活中的含义就是,当一军行动的时候,会引起联合军队的行动。

这样的例子,不仅仅存在战场上,在我们生活中也是如此。红绿灯变绿的时候,所有的汽车都会开动;当号令枪响的时候,所有的运动员都会健步如飞;当下暴雨的时候,所有的人都会躲雨。

示例

业务为红绿灯变绿的时候,所有的汽车都会开动。

渣渣程序

红绿灯

public class TrafficLight {
    private ELightType eLightType;
    private Car car;
    public TrafficLight(Car car) {
        this.car = car;
    }
    public void becomeGreen() {
        eLightType = ELightType.GREEN;
        System.out.println("交通灯变绿了"+eLightType);
    }
    public void becomeYellow() {
        eLightType = ELightType.YELLOW;
        System.out.println("交通灯变黄了"+eLightType);
    }
    public void becomeRed() {
        eLightType = ELightType.RED;
        System.out.println("交通灯变红了"+eLightType);
    }
    public void notifyCar() {
        switch (eLightType) {
            case RED:car.stop();break;
            case GREEN:car.move();break;
            case YELLOW:car.stop();break;
            default:car.stop();
        }
    }
    public enum ELightType {
        GREEN,YELLOW,RED
    }
}

车辆

public class Car {
    private boolean isMove = false;
    //setter、getter方法省略
    public void move() {
        isMove = true;
        System.out.println("汽车开动了"+isMove);
    }
    public void stop() {
        isMove = false;
        System.out.println("汽车停止了"+isMove);
    }
}

程序入口

public class Main {
    public static void main(String[] args) {
        TrafficLight trafficLight = new TrafficLight(new Car());
        trafficLight.becomeGreen();
        trafficLight.notifyCar();
    }
}
//交通灯变绿了GREEN
//汽车开动了true

上面基本上是实现了观察者模式的理念,但是演示了什么叫不面向接口编程,什么叫紧耦合。存在如下问题:

  1. 红绿灯和车辆是紧耦合的,如果我需要添加行人监听,那么我就需要修改交通灯的类,不利于扩展;
  2. 车辆(订阅者)的类的更新方法复杂,没有统一接口,如果添加行人的更新状态根本是不可能的。
  3. 这里提示车辆更新的方法只传递了一个类型,如果这个类型十分复杂的情况下,那么参数很难搞定。

优化

类图

程序

观察者接口与车辆实现

public interface IObserver {
    void update(ISubject subject, Object args);
}
public class Car implements IObserver {
    private boolean isMove = false;
    // 省略setter、getter方法
    public void move() {
        isMove = true;
        System.out.println("汽车开动了"+isMove);
    }
    public void stop() {
        isMove = false;
        System.out.println("汽车停止了"+isMove);
    }
    @Override
    public void update(ISubject subject, Object args) {
        TrafficLight.ELightType type = (TrafficLight.ELightType) args;
        update(type);
    }
    public void update(TrafficLight.ELightType type) {
        switch (type) {
            case RED:stop();break;
            case GREEN:move();break;
            case YELLOW:stop();break;
            default:stop();
        }
    }
}

被观察对象的接口与交通灯实现

public interface ISubject {
    void addObserver(IObserver observer);
    void removeObserver(IObserver observer);
    void removeObservers();
    void notifyObservers(Object args);
    void notifyObservers();//模式里面没有这个方法
}
public class TrafficLight implements ISubject{
    private LinkedTransferQueue<IObserver> observers;
    public TrafficLight() {
        this.observers = new LinkedTransferQueue<>();
    }
    private ELightType eLightType;
    public ELightType geteLightType() {
        return eLightType;
    }
    public void seteLightType(ELightType eLightType) {
        this.eLightType = eLightType;
    }
    public void becomeGreen() {
        eLightType = ELightType.GREEN;
        System.out.println("交通灯变绿了"+eLightType);
    }
    public void becomeYellow() {
        eLightType = ELightType.YELLOW;
        System.out.println("交通灯变黄了"+eLightType);
    }
    public void becomeRed() {
        eLightType = ELightType.RED;
        System.out.println("交通灯变红了"+eLightType);
    }
    @Override
    public void addObserver(IObserver observer) {
        this.observers.add(observer);
    }
    @Override
    public void removeObserver(IObserver observer) {
        this.observers.remove(observer);
    }
    @Override
    public void removeObservers() {
        this.observers.clear();
    }
    @Override
    public void notifyObservers(Object args) {
        for(IObserver observer : observers) {
            observer.update(this, args);
        }
    }
    @Override
    public void notifyObservers() {
        notifyObservers(eLightType);
    }
    public enum ELightType {
        GREEN,YELLOW,RED
    }
}

程序入口

public class Main {
    public static void main(String[] args) {
        ISubject trafficLight = new TrafficLight();
        IObserver car = new Car();

        trafficLight.addObserver(car);
        ((TrafficLight) trafficLight).becomeGreen();
        trafficLight.notifyObservers();
    }
}
//交通灯变绿了GREEN
//汽车开动了true

通过上面的过程,如果我们需要添加一个新的订阅者,那么只需要添加一个新的订阅者并实现IObserver,然后写上相关的update方法就可以,而且这种方式可以增加多个订阅者,不像一开始一样,就只能绑定一个订阅者。

优点

  1. 对象之间的同步通信;
  2. 可以通知一个或多个关联对象;
  3. 对象之间的关系以松耦合关联,不互相一样,增加订阅者类的时候只需要扩展添加新类即可。

缺点

  1. 松耦合导致代码不清晰,难理解;
  2. 通知多个订阅者浪费时间,而且可能会出现系统崩溃等情况;
  3. 如果是异步通知的话,不能保证通知到位;
  4. 通知者并不知道是否通知到位。

应用场景

  1. 监听事件驱动程序设计中的外部事件;
  2. 监听/监视某个对象的变化;
  3. 发布/订阅者模型。

实例

  1. JDK的java.util.Observable和java.util.Observer接口;
  2. MVC模型。

程序

e31_observer_pattern

https://www.jianshu.com/p/a615c709ec25

相关文章

  • 31. 观察者模式

    定义 观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改...

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • 前端面试考点之手写系列

    1、观察者模式 观察者模式(基于发布订阅模式) 有观察者,也有被观察者。 观察者需要放到被观察者列表中,被观察者的...

  • RxJava 原理篇

    一、框架思想 观察者模式观察者自下而上注入被观察者被观察者自上而下发射事件观察者模式 装饰器模式自上而下,被观察者...

  • 观察者模式

    观察者模式概念 观察者模式是对象的行为模式,又叫作发布-订阅(publish/subscrible)模式。 观察者...

  • 设计模式-观察者模式

    观察者模式介绍 观察者模式定义 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为...

  • 观察者模式

    观察者模式 观察者模式的定义 观察者模式(Observer Pattern)也叫做发布订阅模式(Publish/s...

  • iOS设计模式之观察者模式

    观察者模式 1、什么是观察者模式 观察者模式有时又被称为发布(publish)-订阅(Subscribe)模式、模...

  • 观察者模式和发布订阅模式区别

    观察者模式 所谓观察者模式,其实就是为了实现松耦合(loosely coupled)。 在观察者模式中,观察者需要...

网友评论

本文标题:31. 观察者模式

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