【设计模式】观察者模式深度讲解

文章目录

概览

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。以下是关于观察者模式的详细介绍:

一、定义与特点

  1. 定义:观察者模式是一种对象行为模式,用于在对象之间建立一对多的依赖关系,以便当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。
  2. 特点
    • 松耦合:主题和观察者之间通过抽象接口进行交互,使得它们可以独立演化而不影响彼此。
    • 一对多关系:一个主题可以有多个观察者,并且它们之间没有直接联系。
    • 可扩展性:可以随时增加新的观察者或删除现有观察者。
    • 实时性:实现了实时更新机制,当主题状态改变时能够即刻通知相关观察者。

二、角色与职责

在观察者模式中,通常包含以下几个角色:

  1. 抽象主题(Subject)角色:把所有观察者对象保存在一个集合里,提供注册和删除观察者对象的接口。
  2. 具体主题(ConcreteSubject)角色:实现抽象主题角色所提供的接口,当内部状态发生改变时,给所有注册的观察者发出通知。
  3. 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
  4. 具体观察者(ConcreteObserver)角色:实现抽象观察者角色所要求的更新接口,以便在得到主题的通知时更新自身的状态。

三、实现方式

观察者模式的实现方式多种多样,但从根本上说,必须包含观察者和被观察对象两个角色。通常,会定义一个观察者接口和一个主题接口,然后创建具体的观察者和主题类来实现这些接口。主题类中会维护一个观察者列表,并在状态改变时遍历通知所有观察者。

四、应用场景

观察者模式在实际应用中具有广泛的应用场景,包括但不限于以下几个方面:

  1. 事件处理:在图形用户界面(GUI)框架中,按钮的点击事件、窗口的打开和关闭事件等都可以使用观察者模式进行处理。
  2. 消息通知:在消息通知系统中,当发布者发布新消息时,订阅该消息的观察者将收到通知并进行相应的处理。
  3. 发布-订阅系统:观察者模式是发布-订阅模式的核心。当发布者发布新消息或事件时,所有订阅者都会收到通知并执行相应的操作。
  4. 实时数据更新:在需要实时更新数据的应用中,观察者模式可以用于将数据源与数据消费者连接起来。当数据源的数据发生变化时,观察者可以自动获取最新的数据并进行处理。
  5. 库和框架:许多编程库和框架使用观察者模式来支持插件和扩展。开发人员可以编写自定义观察者以响应库或框架中的事件或回调。
  6. 股票市场监测:股票市场应用程序可以使用观察者模式来监测股票价格变化,并将这些变化通知给投资者。
  7. 游戏开发:在游戏中,观察者模式可用于处理各种事件,如玩家输入、碰撞检测、角色状态变化等。
  8. 网络通信:在网络应用中,观察者模式可用于实现即时通信系统,其中用户之间的消息传递可以通过观察者模式来实现。

五、优缺点

  1. 优点

    • 降低了对象之间的耦合度:观察者模式使得主题和观察者之间通过抽象接口进行交互,从而降低了它们之间的耦合度。
    • 增强了系统的可扩展性:由于观察者模式采用了一对多的依赖关系,因此可以很方便地增加新的观察者。
    • 实现了实时更新机制:当主题状态改变时,能够即刻通知相关观察者,从而实现实时更新。
  2. 缺点

    • 如果观察者数量过多,可能会影响性能:因为主题需要遍历所有观察者并通知它们状态的变化,所以如果观察者数量过多,可能会影响系统的性能。
    • 主题只知道观察者发生了变化,但不知道具体发生了什么变化:这可能导致观察者无法做出准确的响应。

综上所述,观察者模式是一种非常有用的设计模式,它能够在对象之间建立松耦合的依赖关系,实现对象之间的动态联动和实时更新。然而,在使用时也需要注意其潜在的缺点和限制。

Java实现

在Java中,观察者模式可以通过接口和类来实现。以下是一个简单的观察者模式的Java代码示例,包括抽象主题(Subject)、具体主题(ConcreteSubject)、抽象观察者(Observer)和具体观察者(ConcreteObserver)。

首先,我们定义抽象主题接口Subject,它包含注册、删除和通知观察者的方法:

java 复制代码
// 抽象主题接口
public interface Subject {
    // 注册观察者
    void registerObserver(Observer observer);
    
    // 删除观察者
    void removeObserver(Observer observer);
    
    // 通知所有观察者
    void notifyObservers();
}

接着,我们定义抽象观察者接口Observer,它包含一个更新方法,用于在主题状态改变时更新观察者:

java 复制代码
// 抽象观察者接口
public interface Observer {
    // 更新观察者
    void update(String message);
}

然后,我们实现具体主题类ConcreteSubject,它实现了Subject接口,并维护一个观察者列表:

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 具体主题类
public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

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

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }

    // 改变状态并通知观察者
    public void setState(String state) {
        this.state = state;
        notifyObservers();
    }

    // 获取状态(通常不需要,但为了完整性而提供)
    public String getState() {
        return state;
    }
}

最后,我们实现具体观察者类ConcreteObserver,它实现了Observer接口:

java 复制代码
// 具体观察者类
public class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " received message: " + message);
    }
}

现在,我们可以使用这些类来测试观察者模式:

java 复制代码
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建具体主题
        ConcreteSubject subject = new ConcreteSubject();

        // 创建具体观察者
        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");
        Observer observer3 = new ConcreteObserver("Observer 3");

        // 注册观察者
        subject.registerObserver(observer1);
        subject.registerObserver(observer2);
        subject.registerObserver(observer3);

        // 改变主题状态并通知观察者
        subject.setState("State has changed!");

        // 删除一个观察者
        subject.removeObserver(observer2);

        // 再次改变主题状态并通知剩余的观察者
        subject.setState("Another state change.");
    }
}

运行ObserverPatternDemo类的main方法,你将看到以下输出:

复制代码
Observer 1 received message: State has changed!
Observer 2 received message: State has changed!
Observer 3 received message: State has changed!
Observer 1 received message: Another state change.
Observer 3 received message: Another state change.

注意,在第二次状态改变时,Observer 2不再收到通知,因为它已经被从观察者列表中删除了。这就是一个简单的Java观察者模式的实现。

Python实现

在Python中,观察者模式可以通过类和接口(在Python中通常使用抽象基类代替接口)来实现。以下是一个简单的Python实现观察者模式的示例。

首先,我们定义一个抽象基类Observer,它包含一个update方法,该方法将在主题状态改变时被调用:

python 复制代码
from abc import ABC, abstractmethod

class Observer(ABC):
    @abstractmethod
    def update(self, message: str):
        pass

接着,我们定义一个Subject类,它维护一个观察者列表,并提供注册、删除和通知观察者的方法:

python 复制代码
class Subject:
    def __init__(self):
        self._observers = []

    def register_observer(self, observer: Observer):
        self._observers.append(observer)

    def remove_observer(self, observer: Observer):
        self._observers.remove(observer)

    def notify_observers(self, message: str):
        for observer in self._observers:
            observer.update(message)

    # 通常还会有一个设置状态的方法,这里为了简单起见,直接提供notify_observers的调用
    def set_state(self, state: str):
        message = f"State has changed to: {state}"
        self.notify_observers(message)

现在,我们可以创建一个具体的观察者类,它继承自Observer抽象基类,并实现update方法:

python 复制代码
class ConcreteObserver(Observer):
    def __init__(self, name: str):
        self.name = name

    def update(self, message: str):
        print(f"{self.name} received message: {message}")

最后,我们可以编写一些代码来测试这个观察者模式:

python 复制代码
if __name__ == "__main__":
    # 创建主题
    subject = Subject()

    # 创建观察者
    observer1 = ConcreteObserver("Observer 1")
    observer2 = ConcreteObserver("Observer 2")
    observer3 = ConcreteObserver("Observer 3")

    # 注册观察者
    subject.register_observer(observer1)
    subject.register_observer(observer2)
    subject.register_observer(observer3)

    # 改变状态并通知观察者
    subject.set_state("New State")

    # 删除一个观察者
    subject.remove_observer(observer2)

    # 再次改变状态并通知剩余的观察者
    subject.set_state("Another New State")

运行上述代码,你将看到以下输出:

复制代码
Observer 1 received message: State has changed to: New State
Observer 2 received message: State has changed to: New State
Observer 3 received message: State has changed to: New State
Observer 1 received message: State has changed to: Another New State
Observer 3 received message: State has changed to: Another New State

注意,在第二次状态改变时,Observer 2不再收到通知,因为它已经被从观察者列表中删除了。

这个示例展示了如何在Python中实现观察者模式。通过使用抽象基类和具体的观察者类,我们可以轻松地扩展和修改这个模式以适应不同的需求。

相关推荐
晨米酱3 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机8 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机9 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤9 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式