【设计模式】【行为型模式(Behavioral Patterns)】之观察者模式(Observer Pattern)

1. 设计模式原理说明

观察者模式(Observer Pattern) 是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合处理事件驱动系统,其中对象之间需要保持同步但又不想紧密耦合。

主要角色
  1. Subject(主题/被观察者):它知道它的观察者是谁。任何数量的观察者都可以观察一个主题。提供注册和删除观察者对象的方法。
  2. Observer(观察者):为那些在主题发生改变时需获得通知的对象定义一个更新接口。
  3. ConcreteSubject(具体主题):将有关状态存储于具体观察者对象;当它的状态发生改变时,向它的各个观察者发出通知。
  4. ConcreteObserver(具体观察者):实现Observer的更新接口以使自身状态与主题的状态保持一致。

2. UML 类图及解释

UML 类图
+------------------+                +-----------------------+
|   Subject        |                |     Observer          |
|------------------|                |-----------------------|
| - observers: List<Observer> |     | - update(message: String): void |
| - register(observer: Observer) |   +-----------------------+
| - unregister(observer: Observer) |   |
| - notifyObservers(message: String) |   |
+------------------+                +-----------------------+
                                                   |
                                                   |
                                                   v
                                    +---------------------------+
                                    | ConcreteObserverA         |
                                    |--------------------------|
                                    | - update(message: String)  |
                                    +---------------------------+
                                                   ^
                                                   |
                                    +---------------------------+
                                    | ConcreteObserverB         |
                                    |--------------------------|
                                    | - update(message: String)  |
                                    +---------------------------+
类图解释
  • Subject:定义了添加、删除和通知观察者的接口。具体主题会实现这些方法,并维护一个观察者列表。
  • Observer:定义了一个更新接口,当主题发生变化时,观察者会被调用。
  • ConcreteSubject:实现了Subject接口,当其状态变化时,会通知所有已注册的观察者。
  • ConcreteObserverA 和 ConcreteObserverB:实现了Observer接口,当收到主题的通知时,会更新自己的状态。

3. 代码案例及逻辑详解

Java 代码案例
// 观察者接口
interface Observer {
    void update(String message);
}

// 具体观察者A
class ConcreteObserverA implements Observer {
    @Override
    public void update(String message) {
        System.out.println("ConcreteObserverA received: " + message);
    }
}

// 具体观察者B
class ConcreteObserverB implements Observer {
    @Override
    public void update(String message) {
        System.out.println("ConcreteObserverB received: " + message);
    }
}

// 被观察者接口
interface Subject {
    void register(Observer observer);
    void unregister(Observer observer);
    void notifyObservers(String message);
}

// 具体被观察者
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();

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

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

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

    public void changeState() {
        // 模拟状态变化
        System.out.println("State changed, notifying observers...");
        notifyObservers("State has been changed!");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();

        Observer observerA = new ConcreteObserverA();
        Observer observerB = new ConcreteObserverB();

        subject.register(observerA);
        subject.register(observerB);

        subject.changeState();

        subject.unregister(observerA);
        subject.changeState();
    }
}
C++ 代码案例
#include <iostream>
#include <vector>
#include <algorithm>

// 观察者接口
class Observer {
public:
    virtual void update(const std::string& message) = 0;
    virtual ~Observer() {}
};

// 具体观察者A
class ConcreteObserverA : public Observer {
public:
    void update(const std::string& message) override {
        std::cout << "ConcreteObserverA received: " << message << std::endl;
    }
};

// 具体观察者B
class ConcreteObserverB : public Observer {
public:
    void update(const std::string& message) override {
        std::cout << "ConcreteObserverB received: " << message << std::endl;
    }
};

// 被观察者接口
class Subject {
private:
    std::vector<Observer*> observers;
public:
    void registerObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void unregisterObserver(Observer* observer) {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notifyObservers(const std::string& message) {
        for (Observer* observer : observers) {
            observer->update(message);
        }
    }

    void changeState() {
        // 模拟状态变化
        std::cout << "State changed, notifying observers..." << std::endl;
        notifyObservers("State has been changed!");
    }
};

// 客户端
int main() {
    Subject subject;

    Observer* observerA = new ConcreteObserverA();
    Observer* observerB = new ConcreteObserverB();

    subject.registerObserver(observerA);
    subject.registerObserver(observerB);

    subject.changeState();

    subject.unregisterObserver(observerA);
    subject.changeState();

    delete observerA;
    delete observerB;

    return 0;
}
Python 代码案例
# 观察者接口
class Observer:
    def update(self, message):
        raise NotImplementedError

# 具体观察者A
class ConcreteObserverA(Observer):
    def update(self, message):
        print(f"ConcreteObserverA received: {message}")

# 具体观察者B
class ConcreteObserverB(Observer):
    def update(self, message):
        print(f"ConcreteObserverB received: {message}")

# 被观察者接口
class Subject:
    def __init__(self):
        self._observers = []

    def register(self, observer):
        self._observers.append(observer)

    def unregister(self, observer):
        self._observers.remove(observer)

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

    def change_state(self):
        # 模拟状态变化
        print("State changed, notifying observers...")
        self.notify_observers("State has been changed!")

# 客户端
if __name__ == "__main__":
    subject = Subject()

    observerA = ConcreteObserverA()
    observerB = ConcreteObserverB()

    subject.register(observerA)
    subject.register(observerB)

    subject.change_state()

    subject.unregister(observerA)
    subject.change_state()
Go 代码案例
package main

import (
	"fmt"
)

// 观察者接口
type Observer interface {
	update(message string)
}

// 具体观察者A
type ConcreteObserverA struct{}

func (c *ConcreteObserverA) update(message string) {
	fmt.Printf("ConcreteObserverA received: %s\n", message)
}

// 具体观察者B
type ConcreteObserverB struct{}

func (c *ConcreteObserverB) update(message string) {
	fmt.Printf("ConcreteObserverB received: %s\n", message)
}

// 被观察者接口
type Subject struct {
	observers []Observer
}

func (s *Subject) register(observer Observer) {
	s.observers = append(s.observers, observer)
}

func (s *Subject) unregister(observer Observer) {
	for i, obs := range s.observers {
		if obs == observer {
			s.observers = append(s.observers[:i], s.observers[i+1:]...)
			break
		}
	}
}

func (s *Subject) notifyObservers(message string) {
	for _, observer := range s.observers {
		observer.update(message)
	}
}

func (s *Subject) changeState() {
	// 模拟状态变化
	fmt.Println("State changed, notifying observers...")
	s.notifyObservers("State has been changed!")
}

// 客户端
func main() {
	subject := &Subject{}

	observerA := &ConcreteObserverA{}
	observerB := &ConcreteObserverB{}

	subject.register(observerA)
	subject.register(observerB)

	subject.changeState()

	subject.unregister(observerA)
	subject.changeState()
}

4. 总结

观察者模式 是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式特别适用于事件驱动系统,其中对象之间需要保持同步但又不想紧密耦合。

主要优点
  1. 松耦合:观察者和被观察者之间的依赖关系非常松散,观察者不需要知道被观察者的具体实现细节。
  2. 支持广播通信:被观察者可以向所有注册的观察者广播消息,无需关心观察者的具体类型。
  3. 灵活性高:可以动态地添加或删除观察者,而不会影响其他观察者。
主要缺点
  1. 过度通知:如果被观察者的状态频繁变化,可能会导致大量不必要的通知。
  2. 复杂性增加:引入观察者模式会增加系统的复杂性,特别是当观察者和被观察者之间存在复杂的依赖关系时。
  3. 调试困难:由于观察者模式涉及多个对象之间的交互,调试时可能比较困难。
适用场景
  • 当一个对象的改变需要同时改变其他对象,而且不知道具体有多少对象需要改变时。
  • 当一个对象需要在另一个对象的状态发生变化时自动更新,但又不想紧密耦合时。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面,将这两者封装在独立的对象中以提高可复用性和灵活性时。
相关推荐
捕鲸叉1 小时前
C++设计模式之组合模式中适用缓存机制提高遍历与查找速度
c++·设计模式·组合模式
夏旭泽1 小时前
设计模式-工厂模式
设计模式·简单工厂模式
渊渟岳2 小时前
设计模式--原型模式及其编程思想
设计模式
春风十里不如你95273 小时前
【设计模式】【创建型模式(Creational Patterns)】之建造者模式(Builder Pattern)
设计模式·建造者模式
春风十里不如你95275 小时前
【设计模式】【结构型模式(Structural Patterns)】之代理模式(Proxy Pattern)
设计模式·代理模式
请你打开电视看看9 小时前
观察者模式
java·观察者模式·设计模式
Mr.朱鹏9 小时前
设计模式之策略模式-工作实战总结与实现
java·spring·设计模式·kafka·maven·策略模式·springbbot
春风十里不如你95279 小时前
【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)
设计模式·组合模式
捕鲸叉9 小时前
C++设计模式之组合模式实践原则
c++·设计模式·组合模式