观察者模式是一种一对多的依赖关系,当主题状态改变时,所有观察者自动收到通知并更新。它通过抽象接口实现主题与观察者的解耦,提升系统可扩展性与维护性,广泛应用于事件驱动系统如GUI、MVC、消息队列等。实现时需注意通知风暴、内存泄漏和调试复杂性等陷阱。

观察者模式,在我看来,它本质上是一种“一对多”的对象依赖关系。简单来说,当一个对象(我们称之为“主题”或“发布者”)的状态发生变化时,所有依赖于它的对象(“观察者”或“订阅者”)都会自动收到通知并更新。这就像你订阅了一份报纸,当报社出版了新一期(状态变化),你作为订阅者就会收到它。它提供了一种机制,让对象之间能够松散地通信,而无需彼此紧密耦合。
观察者模式的核心在于解耦。它让主题对象不再需要知道具体观察者的类型,也不需要知道它们是如何更新的。主题只维护一个观察者列表,并在自身状态改变时遍历这个列表,调用每个观察者的通用更新方法。
这个模式通常包含几个关键角色:
attach
detach
整个流程大致是这样:观察者先向感兴趣的主题注册自己。当主题的某个关键状态发生变化时,它会遍历内部的观察者列表,并逐一调用每个观察者的更新方法,把变化信息传递过去。观察者收到信息后,根据自身逻辑进行处理。
我个人觉得,观察者模式最核心的价值就是“解耦”。在软件设计中,我们总是在追求低耦合、高内聚。如果一个对象的改变直接导致另一个对象也必须跟着改变,并且这种改变是直接通过硬编码的调用实现的,那么当系统变得复杂时,维护起来简直是噩梦。
观察者模式提供了一个优雅的解决方案:
它不仅仅是提供了一种通知机制,更是一种管理复杂依赖关系、提升系统柔韧性的设计哲学。
要实现观察者模式,我们可以从定义抽象基类或接口开始,然后具体实现它们。这里我用Python来演示一个简单的“气象站”例子,气象站是主题,手机显示和网页仪表盘是观察者。
# 抽象主题 (Subject)
class Subject:
def __init__(self):
self._observers = [] # 存储观察者的列表
def attach(self, observer):
"""添加一个观察者"""
if observer not in self._observers:
self._observers.append(observer)
print(f"Observer {observer.__class__.__name__} attached.")
def detach(self, observer):
"""移除一个观察者"""
try:
self._observers.remove(observer)
print(f"Observer {observer.__class__.__name__} detached.")
except ValueError:
print(f"Observer {observer.__class__.__name__} not found.")
def notify(self, message):
"""通知所有观察者"""
print("\nNotifying observers...")
for observer in self._observers:
observer.update(message)
# 抽象观察者 (Observer)
class Observer:
def update(self, message):
"""接收主题通知并更新"""
raise NotImplementedError("Subclasses must implement update method")
# 具体主题 (ConcreteSubject)
class WeatherStation(Subject):
def __init__(self, location):
super().__init__()
self._location = location
self._temperature = None
print(f"Weather Station at {self._location} created.")
def set_temperature(self, temp):
"""设置温度,并通知观察者"""
if self._temperature != temp: # 只有温度变化才通知
print(f"\n--- Weather Station at {self._location}: Temperature changing from {self._temperature} to {temp}°C ---")
self._temperature = temp
self.notify(f"New temperature in {self._location}: {self._temperature}°C")
else:
print(f"\nWeather Station at {self._location}: Temperature is still {temp}°C, no change.")
def get_temperature(self):
return self._temperature
# 具体观察者 (ConcreteObserver)
class PhoneDisplay(Observer):
def __init__(self, name):
self._name = name
print(f"Phone Display '{self._name}' created.")
def update(self, message):
print(f"[{self._name} Phone Display]: Received update - {message}")
class WebDashboard(Observer):
def __init__(self, name):
self._name = name
print(f"Web Dashboard '{self._name}' created.")
def update(self, message):
print(f"[{self._name} Web Dashboard]: Displaying - {message}")
# 实际使用
if __name__ == "__main__":
station = WeatherStation("New York")
phone1 = PhoneDisplay("My iPhone")
dashboard = WebDashboard("Admin Panel")
phone2 = PhoneDisplay("Family Tablet")
# 注册观察者
station.attach(phone1)
station.attach(dashboard)
station.attach(phone2)
# 温度变化,通知所有观察者
station.set_temperature(25)
station.set_temperature(25) # 再次设置相同温度,不应通知
# 移除一个观察者
station.detach(phone1)
# 再次变化,看看谁还会收到通知
station.set_temperature(28)
# 尝试移除一个不存在的观察者
station.detach(PhoneDisplay("Non Existent"))这个例子展示了“推送”模型,即主题在通知时直接将数据(
message
_observers
观察者模式在软件开发中非常普遍,它几乎无处不在,只是我们可能没有意识到它就是观察者模式的变体。
常见应用场景:
潜在陷阱:
所以,虽然观察者模式非常强大和有用,但在实际应用中,我们需要权衡其优点和可能带来的复杂性,并注意规避上述陷阱。
以上就是什么是观察者模式?观察者的实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号