观察者模式.

一、概念

  • 观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
  • 观察者模式四个角色:  1、抽象主题:定义对观察者管理的接口,包括 订阅、取消订阅、通知接口。  2、具体主题:把所有观察者对象的引用保存在一个聚集(比如ArrayList对象)里,实现抽象主题的接口,并在更新时通知观察者。  3、抽象观察者:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。  4、具体观察者:实现抽象观察者定义的接口,得到主题通知的数据(pull or push),并实现自己的逻辑。
  • 主题 + 观察者 = 观察者模式,可以用报纸订阅服务来模拟这个模式 —— 报纸是主题,订阅报纸的人是观察者。观察者可以选择是否订阅或者退订主题。

二、Demo实现

1、主题

java.util 包中内置了一个抽象主题 Observable 类(有弊端,下文会提到),可以选择继承 Observable 类作为具体主题角色。

@AllArgsConstructor
@Getter
public class WeatherData extends Observable {
    /**
     * 温度
     */
    private Float temperature;
    /**
     * 湿度
     */
    private Float humidity;
    /**
     * 压力
     */
    private Float pressure;
    
    
    /**
     * 假设改变的时候这个方法会被调用
     */
    public void measurementsChanged() {
        setChanged();
        notifyObservers(); // 这种不带参数的方式,由观察者 pull 自己想要的数据。要什么数据由观察者自己决定。
        //notifyObservers(Object arg) // 这种带参数的方式,由主题 push 数据。传什么数据由主题决定。(推荐)
    }
}

2、观测者

java.util 包中内置了一个抽象观察者 Observer 接口,可以选择实现 Observer 接口的 update 方法作为具体观察者角色,做更新的操作。

湿度观察者:

public class HumidityObserver implements Observer {

    public HumidityObserver(Observable observable) {
        // 订阅主题
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            Float humidity = weatherData.getHumidity();
            System.out.println("我是一个湿度观察者,我现在的湿度是:" + humidity);
        }
    }
}

压力观察者:

public class PressureObserver implements Observer {
    
    public PressureObserver(Observable observable) {
        // 订阅主题
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            Float pressure = weatherData.getPressure();
            System.out.println("我是一个压力观察者,我现在的压力是:" + pressure);
        }
    }
}

温度观察者:

public class TemperatureObserver implements Observer {
    
    public TemperatureObserver(Observable observable) {
        // 订阅主题
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            Float temperature = weatherData.getTemperature();
            System.out.println("我是一个温度观察者,我现在的温度是:" + temperature);
        }
    }
}

3、测试

public static void main(String[] args) {
    // 具体主题实现
    WeatherData weatherData = new WeatherData(24.0F,152F,100F);
    // 观察者订阅
    new HumidityObserver(weatherData);
    new PressureObserver(weatherData);
    new TemperatureObserver(weatherData);
    // 事件发生
    weatherData.measurementsChanged();
}

4、Observable 的弊端

  • Observable 是一个“类”,而不是一个接口。所以你只能选择继承它,实现自己的具体主题,这大大限制了 Observable 的复用潜力,毕竟 Java 不支持多重继承。
  • Observable 的 setChanged 方法是 protected 属性的,因此你除了选择继承 Observable 类,甚至无法使用组合来使用它。
  • 如果有必要的话可以实现自己的 Observable 接口,不要害怕,这并不难。(链接代码中有示例)

tips:"抽象"主题 和 具体主题标反了。汗~

演示源代码:https://github.com/JMCuixy/design-patterns

三、总结

  • 设计原则:观察者模式是为了交互对象之间的松耦合设计而努力。
  • 应用场景:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
  • 优点:主题是真正拥有数据的人,观察者是主题的依赖者,在数据变化时更新,这样比起让许多对象控制通一份数据类,可以得到更加干净的OO设计。
  • 缺点:在应用观察者模式时需要考虑一下开发效率和运行效率的问题,因为在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,我们一般会采用异步实现。而且必须保证投递是以自恰的方式进行的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术栈

史上最全 BAT 大厂面试题整理!(速度收藏)

3344
来自专栏GIS讲堂

leaflet加载天地图

leaflet是一个轻量级的并且开源的地图框架,是由esri发起的,由于其轻量、简单而被大家喜欢,本文带你学习如何在leaflet中加载天地图。

6083
来自专栏小樱的经验随笔

CTF---Web入门第八题 Guess Next Session

Guess Next Session分值:10 来源: iFurySt 难度:易 参与人数:3870人 Get Flag:1672人 答题人数:1690人 ...

3919
来自专栏企鹅号快讯

phpjiami 数种解密方法

Pwnhub公开赛出了个简单的PHP代码审计题目,考点有两个: 如果说仅为了做出题目拿到flag,这个题目太简单,后台也有数十名选手提交了答案和writeup。...

5537
来自专栏java一日一条

编写可靠 Shell 脚本的 8 个建议

这八个建议,来源于键者几年来编写 shell 脚本的一些经验和教训。事实上开始写的时候还不止这几条,后来思索再三,去掉几条无关痛痒的,最后剩下八条。毫不夸张地说...

962
来自专栏苦逼的码农

设计模式走一遍---观察者模式

红灯车过,人停;绿灯人过,车停。每天走在马路上,到处可见红绿灯指挥着我们什么时候可以过马路,什么时候不能过马路。无论是人还是车,都时刻关注着红绿灯的状态,一旦红...

782
来自专栏技术与生活

设计模式-命令模式

Client:确定具体的命令和接受者; Command:抽象命令接口,一般是接口类或者抽象类 ConcreteCommand:具体的命令执行,调用接受者 Inv...

1245
来自专栏码神联盟

碎片化 | 第四阶段-46-值栈valueStack介绍和原理-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/q0567vth0ol.html ValueStack 值栈:(接口) ...

35717
来自专栏技术小黑屋

这就是观察者模式

观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的...

1427
来自专栏Phoenix的Android之旅

重新认识观察者模式

对于观察者模式,我们知道它是设计模式的一种, 利用接口将数据和使用数据的对象进行解耦。 如果你是个老鸟的话,就知道 Java的 util的 Observer接口...

812

扫码关注云+社区

领取腾讯云代金券