模式

观察者模式

观察者模式又叫发布-订阅模式模型-视图模式从属者模式。我们希望用一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知。使用观察者模式,能够完美地将观察者和被观察的对象分离。一般在消息交换、多级触发等场景下使用。

观察者模式的优点有:

  • 观察者与被观察者之间抽象耦合
  • 可以触发多个符合单一职责的模块
  • 可以很方便地实现广播

但是也有效率可能不高的缺点。

实现示例

我们来通过一个案例来看看观察者模式具体做了什么。

首先,我们定义一个主题,比如是股票市场主题的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 抽象主题类
class Subject:
def __init__(self):
self.observers=[] # 观察者列表

def addObserver(self,observer):
self.observers.append(observer) # 添加观察者

def notifyAll(self,info):
for observer in self.observers: # 通知观察者
observer.update(info)

class Stock(Subject):
def __init__(self,name,price):
super().__init__() # 初始化股票的属性
self._name=name
self._price=price

@property
def price(self): # 一个股票价格的只读属性
return self._price

@price.setter
def price(self,value): # 修改股票价格的方法
if self._price>value: # 根据股票价格变化通知给观察者具体的信息
info=f"Stock {self._name}'s price decrease from {self._price} to {value}"
self.notifyAll(info)
elif self._price<value:
info=f"Stock {self._name}'s price increase from {self._price} to {value}"
self.notifyAll(info)
self._price=value

接下来我们定义一个观察者类,在这个案例中就是关注这支股票的投资者们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Observer: # 观察者抽象类
def update(self,info):
pass

class Investor(Observer): # 观察者具体类
def __init__(self,name):
self._name=name

@property
def name(self): # 观察者信息
return self._name

def update(self,info): # 通知观察者信息
print(f"Dear\t{self._name}\tAlarm:{info}")

让我们运行一下看看结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
s=Stock("平安银行",11.0) # 一个平安银行股票主题,当前价格为11
for i in range(5): # 创建5个关注股票主题投资观察者,名字为I1-I5
inv=Investor("I" + str(i+1))
s.addObserver(inv)
s.price=8.0 # 此时价格变为8,看看发生了什么
s.price=17.0 # 此时价格又变为17,看看发生了什么

# output:
# Dear I1 Alarm:Stock 平安银行's price decrease from 11.0 to 8.0
# Dear I2 Alarm:Stock 平安银行's price decrease from 11.0 to 8.0
# Dear I3 Alarm:Stock 平安银行's price decrease from 11.0 to 8.0
# Dear I4 Alarm:Stock 平安银行's price decrease from 11.0 to 8.0
# Dear I5 Alarm:Stock 平安银行's price decrease from 11.0 to 8.0
# Dear I1 Alarm:Stock 平安银行's price increase from 8.0 to 17.0
# Dear I2 Alarm:Stock 平安银行's price increase from 8.0 to 17.0
# Dear I3 Alarm:Stock 平安银行's price increase from 8.0 to 17.0
# Dear I4 Alarm:Stock 平安银行's price increase from 8.0 to 17.0
# Dear I5 Alarm:Stock 平安银行's price increase from 8.0 to 17.0