设计模式学习笔记(二)——观察者模式

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

分析: 一对多依赖,我们可以理解为一个主题对应多个观察者,主题对象管理某些数据,观察者需要注册主题以便在主题数据更改时收到通知,当主题内数据发生改变,就会通知观察者。

使用场景:
1.对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2.对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

设计原则: 观察者模式提供了一个新的对象设计,让主题和观察者之间松耦合。主题唯一依赖的只是一个实现了Observer接口的对象列表,不知道具体类是什么或如何实现等细节,所以我们可以随时增加,删除,或修改观察者。我们可以独立地复用主题或观察者,即如果在别的地方需要用到主题或观察者,可以轻易地使用,改变一方不会影响另一方。
原则:为了交互对象之间的松耦合设计而努力

UML图

在这里插入图片描述

subject:抽象主题,规定了具体主题需要实现的方法
observer:抽象观察者,规定了具体观察者用来更新的方法
concreteSubject:具体主题,包含了变化的数据,持有一个包含所有观察者引用的列表集合
concreteObserver:具体观察者,包含一个抽象主题类型的用于存放具体主题引用的变量,以便于观察者注册或删除

示例

一个气象观测站应用,有三个布告板,分别显示目前的状况,气象统计和简单的预报。当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新,同时,这个应用需要扩展,提供一组API,可以让别的开发人员写出自己的布告板并插入
分析: 主题:WeatherObject,观察者:布告板。我们只要提供主题接口和观察者接口,并用具体类去实现,即可完成需求。
代码:

抽象主题


public interface Subject {
    void registerObserver(Object object);
    void removeObserver(Object object);
    void notifyObservers();
}

抽象观察者

public interface Observer {
    void update(float temp,float humidity,float pressure);
}

//布告板需要显示数据时,调用此接口
public interface DisplayElement {
    void display();
}

具体主题

public class WeatherData implements Subject {

    private ArrayList observers;
    private float temp;
    private float humidity;
    private float pressure;

    public WeatherData() {
        this.observers = new ArrayList();
    }

    @Override
    public void registerObserver(Object object) {
        observers.add(object);
    }

    @Override
    public void removeObserver(Object object) {
        int i = observers.indexOf(object);
        if(i>=0){
            observers.remove(i);
        }
    }

    @Override
    public void notifyObservers() {

        for(int i = 0;i<observers.size();i++){
            Observer observer = (Observer) observers.get(i);
            observer.update(temp,humidity,pressure);
        }
    }

    //从气象台获取新数据时,通知观察者
    public void measurementsChanged(){
        notifyObservers();
    }

    public void setMeasurements(float temp,float humidity,float pressure){
        this.temp = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

}

具体观察者

public class CurrentConditionDisplay implements Observer, DisplayElement {

    private float temp;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temp = temp;
        this.humidity = humidity;
        this.display();
    }

    @Override
    public void display() {
        System.out.println("当前温度:"+temp);
        System.out.println("当前湿度:"+humidity);
    }
}

测试

public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
        weatherData.setMeasurements(32,50.1f,100);

    }
}

结果:
在这里插入图片描述
当然,我们在这里只实现了一个布告板,但其余两个或是多个布告板的类,只要实现了Observer接口,并按符合条件编写,也是很容易实现。

问题

在示例中,主题在每次更新数据时,都会将一堆数据推送给所有观察者,如果有某些观察者不需要这么多条数据或者是想要主动获取需要的数据呢?
答: 有两种观察者获得状态的方法。第一种是”推“,即示例中的方法,由主题一次性将所有数据推送到观察者中;第二种是”拉“,主题提供公有的getter,更新时,由观察者本身决定获取哪一些数据。

另外: java API提供了内置的观察者模式,java.util包提供了Observer接口和Observable类,这和我们的Observer接口和Subject接口基本是一致的,但它使用上更方便一点,因为功能都事先准备好了

JAVA内置的观察者模式

  • 如何把对象变为观察者
    和以往类似,实现java.util.Observer,然后调用Observable对象的addObserver()方法,不想当观察者时,调用其deleteObserver()方法
  • 主题如何送出通知
    主题类继承java.util.Observable,然后
    1、先调用setChanged(),标记数据已经改变,不调用此方法,观察者不会被通知
    2、然后调用notifyObservers()或notifyObservers(Object arg),后者可传送任何数据给观察者
  • 观察者如何接收通知
    观察者更新方法,update(Observable o,Object arg),第一个参数为主题,好让观察者知道是哪个主题通知它的,第二个参数为数据对象,没有即为空

缺陷: 由于Observable是一个类,而JAVA是单继承,所以当想同时具有Observable和另一个超类的行为时,就会陷入困难。
另一点是不能创建自己的实现,例如setChanged方法,我们看源码的话,会发现它是一个protected的方法,所以除非你继承了Observable,否则你没办法创建Observable并组合到你自己的对象中,这违反了”多用组合,少用继承“的设计原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
cda备考学习学习笔记——基础知识篇()主要涉及了计算机科学与技术领域的基本概念和知识。 首先,它介绍了计算机网络的基础知识。网络是将多台计算机通过通信链路连接起来,使它们能够相互通信和共享资源的系统。笔记详细介绍了网络的组成、拓扑结构和通信协议等重要内容。 其次,笔记还解释了计算机系统的基本组成。计算机系统由硬件和软件两部分组成,其硬件包括央处理器、存储器、输入输出设备等,而软件则分为系统软件和应用软件。笔记详细介绍了各种硬件和软件的功能和作用。 此外,笔记还对数据库管理系统进行了介绍。数据库管理系统是一种用于管理和组织数据的软件系统,它能够实现数据的存储、检索和更新等操作。笔记详细介绍了数据库的概念、结构和操作等内容。 最后,笔记还包括了算法和数据结构的基础知识。算法是解决问题的一系列步骤和规则,而数据结构则是组织和存储数据的方式。笔记介绍了常用的算法和数据结构,如排序算法、树和图等。 总之,通过学习CDA备考学习笔记的基础知识篇(),我们能够更好地理解计算机网络、计算机系统、数据库管理系统以及算法和数据结构等相关概念和知识。这些基础知识对于我们深入研究计算机科学与技术领域是非常重要的,也为我们日后的学习和工作奠定了坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值