《Head First 设计模式》第二章 - 笔记

本书是本人写的设计模式的笔记,写下核心要点,如果你掌握过设计模式,想快速阅读本书内容,这个笔记适合你阅读。如果你是新手,有 java 基础和 oo 设计原则基础,你适合跟我一样从零阅读本书。

第一章 观察者模式

报社的发布和订阅与观察者模式工作原理相似,报社发布报纸,个体户订阅报纸。

发布+订阅 = 观察者模式

在观察者模式中,发布叫做主题,订阅叫做观察者。如下图

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

来看类图

设计原则之一 松耦合

松耦合:主题只知道观察者实现了某个接口,主题不知道观察者的具体类是谁,任何时候我们都可以增加新的观察者,因为主题唯一依赖的东西是一个实现Observer接口的对象列表,运行时还可以用新的观察者替代现有的观察者,新的观察者出现主题

代码不需要更改。观察者随意变化,又具有很好的封装性。主题与观察者之间是松耦合,因为改变主题或观察者的任意一方,都不会影响到另一方。

设计

设计气象站

代码实现

更好的代码阅读可访问本人github:GitHub - FencyJay/head-frist-design-pattern: 《Head First 设计模式》笔记以及书本实例

主题接口

java 复制代码
/**
 * 气象站主题接口
 *
 * @Author fency
 * @Date 2025/5/19 15:52
 * @Version 1.0
 */

public interface Subject {
    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();
}

观察者接口

为了遵循单一职责原则 (SRP)和 接口隔离原则(ISP) , 观察者模式中的职责分为两个接口

  • Observer 接口只负责接收主题(Subject)推送的状态更新(update(...))。
  • DisplayElement 接口只负责定义展示行为(display())。

这个设计也体现出松耦合,当你仅仅实现DispalyElemnt时,你的具体类就是一个简单的气象展示对象,没有推送功能。

java 复制代码
/**
 * 气象站观察者接口
 *
 * @Author fency
 * @Date 2025/5/19 15:53
 * @Version 1.0
 */

public interface Observer {
    void update(float temperature, float humidity, float pressure);
}
java 复制代码
/**
 * 气象站显示元素接口
 *
 * @Author fency
 * @Date 2025/5/19 15:54
 * @Version 1.0
 */

public interface DisplayElement {
    void display();
}

主题接口实现

java 复制代码
/**
 * 气象站主题类
 * 
 * @Author fency
 * @Date 2025/5/19 15:55
 * @Version 1.0
 */

public class WeatherData implements Subject{

    private ArrayList observers;
    private float temperature;
    private float humidity;
    private float pressure;

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

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        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(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

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

}

观察者实现类

java 复制代码
/**
 * 当前气象状况
 *
 * @Author fency
 * @Date 2025/5/19 16:00
 * @Version 1.0
 */

public class CurrentConditionsDisplay implements Observer,DisplayElement{

    private float temperature;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData){
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }


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

    @Override
    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}
java 复制代码
/**
 * 统计气象信息
 *
 * @Author fency
 * @Date 2025/5/19 16:10
 * @Version 1.0
 */

public class StatisticsDisplay implements Observer,DisplayElement{

    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherData;

    public StatisticsDisplay(Subject weatherData){
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

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

    @Override
    public void display() {
        System.out.println("Statistics conditions: " + temperature + "F degrees and " + humidity + "% humidity" + " and " + pressure + " pressure");

    }

}

我对观察者模式的理解:

  1. 解耦
  • Subject(主题/被观察者) :定义注册、移除、通知观察者的接口。在示例中,由 WeatherData 实现。
  • Observer(观察者) :定义 update(...) 方法,当主题状态改变时被调用。各显示器类(CurrentConditionsDisplayStatisticsDisplay 等)都实现了它。
  1. 扩展性
  • 只要实现了 ObserverDisplayElement 接口,就可以随时新增新的显示板块(比如手机端显示、图表显示等),无需改动已有代码,符合"开闭原则"。
  1. 优点
  • 松耦合:主题只知道观察者接口,反之亦然,双方不直接依赖具体类;
  • 灵活可扩展:可动态增删观察者、添加新观察者类型;
  • 职责单一:主题负责管理数据和通知,观察者专注于如何响应和展示。
相关推荐
fmk10231 小时前
TailwindCSS 学习笔记
笔记·学习
摇滚侠2 小时前
Vue 项目实战《尚医通》,完成确定挂号业务,笔记46
java·开发语言·javascript·vue.js·笔记
摇滚侠2 小时前
Vue 项目实战《尚医通》,完成取消预约业务,笔记49
vue.js·笔记
Just right2 小时前
AndroidApp笔记环境配置
笔记
xinxingrs2 小时前
贪心算法、动态规划以及相关应用(python)
笔记·python·学习·算法·贪心算法·动态规划
四谎真好看3 小时前
Java 黑马程序员学习笔记(进阶篇28)
java·笔记·学习·学习笔记
Oll Correct3 小时前
Excel基础操作(二)
笔记·excel
hd51cc3 小时前
文档与视图 学习笔记
笔记·学习
y***54883 小时前
Java设计模式之观察者模式
观察者模式·设计模式
明洞日记4 小时前
【设计模式手册010】组合模式 - 树形结构的优雅处理
java·设计模式·组合模式