设计模式学习(三) 观察者模式

本文深入讲解了观察者模式,一种让对象间建立一对多依赖关系的设计模式,使得当一个对象状态变化时,所有依赖对象都能自动更新。通过报纸订阅的例子,详细介绍了观察者模式的工作原理,包括Subject和Observer接口的实现,以及如何在Java中利用内置的Observable类和Observer接口来实现这一模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引入


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

认识观察者模式

例子:报纸和杂志的订阅

1.报社的业务就是出版报纸

2.向某家报社订阅报纸,只要有新的报纸出版,就会一直为你送报纸

3.当你取消了订阅后,将不会为你送新报纸

4.只要报社在运营,就会一直有人或单位订阅报纸或取消订阅。

出版社+订阅者=观察者 模式

UML类图

以上包含subject与observer接口的类设计最为常见

1.subject主题接口,对象使用此接口注册为观察者或者把自己从观察者中删除

2.observer所有的观察者必须实现此接口,这个接口只有一个update方法。当主题状态改变时它被调用

3.ConcreteSubject一个具体主题实现了主题接口,除了注册和撤销方法,还实现了notifyObserver方法,此方法在主题 状态改变时更新所有当前观察者

4.具体的观察者可以是实现Observer接口的任意类,观察者必须注册主题,以便接受更新

 

示例

这里引用head first上一个例子

 

 

package com.zpkj.project4;
/**
 * subject接口
 */
public interface SubjectInter {
    
    void registerObserver(ObserverInter observerInter);
    
    void removeObserver(ObserverInter observerInter);
    
    void notifyObserver();
}
package com.zpkj.project4;

/**
 * Observer接口
 */

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

}

 

package com.zpkj.project4;

import java.util.ArrayList;

/**
 *  ConcreteSubject 实现类 
 */

public class WeatherData implements SubjectInter{
    
    private ArrayList<ObserverInter> observerInters;
    
    private float temperature;
    
    private float humidity;
    
    private float pressure;
    
    
    public WeatherData() {
        super();
        observerInters  =new ArrayList<ObserverInter>();
    }
    

    @Override
    public void registerObserver(ObserverInter observerInter) {
        observerInters.add(observerInter);
        
    }

    @Override
    public void removeObserver(ObserverInter observerInter) {
        int num = observerInters.indexOf(observerInter);
        if(num>=0){
            observerInters.remove(num);
        }
    }

    @Override
    public void notifyObserver() {
        for(int i = 0;i < observerInters.size();i++){
            ObserverInter observerInter = observerInters.get(i);
            observerInter.update(temperature, humidity, pressure);
        }
        
    }
    
    public void measurementsChanged(){
        notifyObserver();
    }
    
    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

}


 

package com.zpkj.project4;

/**
 * ConcreteObserver 实现类 
 */

public class CurrentConditionsDisplay implements ObserverInter,DisplayElementInter{
    
    private SubjectInter weatherData;
    
    private float temperature;
    
    private float humidity;
    
    private float pressure;
    
    public CurrentConditionsDisplay(SubjectInter subjectInter){
        super();
        this.weatherData = subjectInter;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("气温:"+temperature+" 湿度:"+humidity+" 压力:"+pressure);
    }

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

}
/**
 * 负责显示天气信息接口
 */

package com.zpkj.project4;

public interface DisplayElementInter {
    
    void display();

}

总结

有几点需要注意的是

  1. Subject 和 Observer 是一个一对多的关系,也就是说观察者只要实现 Observer 接口并把自己注册到 Subject 中就能够接收到消息事件;
  2. Java API有内置的观察者模式类:java.util.Observable 类和 java.util.Observer 接口,这分别对应着 Subject 和 Observer 的角色;
  3. 使用 Java API 的观察者模式类,需要注意的是被观察者在调用 notifyObservers() 函数通知观察者之前一定要调用 setChanged() 函数,要不然观察者无法接到通知;
  4. 使用 Java API 的缺点也很明显,由于 Observable 是一个类,java 只允许单继承的缺点就导致你如果同时想要获取另一个父类的属性时,你只能选择适配器模式或者是内部类的方式,而且由于 setChanged() 函数为 protected 属性,所以你除非继承 Observable 类,否则你根本无法使用该类的属性,这也违背了设计模式的原则:多用组合,少用继承。

引用

[1] 弗里曼. Head First 设计模式(中文版)[Z]. 中国电力出版社: O'Reilly Taiwan公司 ,2007.

  https://blog.youkuaiyun.com/self_study/article/details/51346849

源码下载

https://github.com/isheroleon/design

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值