觀察者.png
思想:觀察者模式類似于redis中的訂閱和發(fā)布,只有加入觀察者列表的砸逊,才能接受到發(fā)布的消息璧南,一旦有所改變,則會一一通知觀察者進(jìn)行更新师逸。這里案例二仿照現(xiàn)實(shí)生活中的紅綠燈司倚,行人、汽車篓像、自行車都可以充當(dāng)觀察者动知,紅綠燈為被觀察者,也是訂閱的消息员辩,根據(jù)紅綠燈的變化盒粮,若是紅燈,則他們?nèi)考尤胗^察者奠滑,駐足等待丹皱。若是綠燈,則均可通行宋税,從觀察者列表中移除摊崭。
意圖:
定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時, 所有依賴于它的對象都得到通知并被自動更新。
適用性:
當(dāng)一個抽象模型有兩個方面, 其中一個方面依賴于另一方面杰赛。將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立地改變和復(fù)用呢簸。
當(dāng)對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。
當(dāng)一個對象必須通知其它對象,而它又不能假定其它對象是誰根时。換言之, 你不希望這些對象是緊密耦合的嘿架。
案例一
'''
Observer
'''
class Subject(object):
def __init__(self):
self._observers = []
def attach(self, observer):
if not observer in self._observers:
self._observers.append(observer)
def detach(self, observer):
try:
self._observers.remove(observer)
except ValueError:
pass
def notify(self, modifier=None):
for observer in self._observers:
if modifier != observer:
observer.update(self)
# Example usage
class Data(Subject):
def __init__(self, name=''):
Subject.__init__(self)
self.name = name
self._data = 0
@property
def data(self):
return self._data
@data.setter
def data(self, value):
self._data = value
self.notify()
class HexViewer:
def update(self, subject):
print('HexViewer: Subject %s has data 0x%x' %
(subject.name, subject.data))
class DecimalViewer:
def update(self, subject):
print('DecimalViewer: Subject %s has data %d' %
(subject.name, subject.data))
# Example usage...
def main():
data1 = Data('Data 1')
data2 = Data('Data 2')
view1 = DecimalViewer()
view2 = HexViewer()
data1.attach(view1)
data1.attach(view2)
data2.attach(view2)
data2.attach(view1)
print("Setting Data 1 = 10")
data1.data = 10
print("Setting Data 2 = 15")
data2.data = 15
print("Setting Data 1 = 3")
data1.data = 3
print("Setting Data 2 = 5")
data2.data = 5
print("Detach HexViewer from data1 and data2.")
data1.detach(view2)
data2.detach(view2)
print("Setting Data 1 = 10")
data1.data = 10
print("Setting Data 2 = 15")
data2.data = 15
if __name__ == '__main__':
main()
案例二:紅綠燈
import time
# 定義一個紅綠燈的類型
class TrfficLight:
def __init__(self):
self.color = 'red'
# 這是觀察者列表
self.__observers = []
# 定義一個方法,符合條件的加入觀察者列表
def join_observers(self, observer):
if self.color == 'green':
print("直接通行")
else:
if observer not in self.__observers:
print("加入觀察者")
self.__observers.append(observer)
print("駐足等待")
# 定義一個方法啸箫,清空觀察者列表
def set_color(self):
# 將紅綠燈顏色設(shè)置為綠色
self.color = 'green'
# 觀察者依次通行
for observer in self.__observers:
observer.run()
# 清空觀察者列表
self.__observers = []
# 定義三種觀察者
class Person:
def run(self):
print("行人緩慢通行")
class Bike:
def run(self):
print("自行車勻速通行")
class Car:
def run(self):
print("汽車快速通過")
# 創(chuàng)建一個紅綠燈類型,默認(rèn)為紅燈
light=TrfficLight()
# 創(chuàng)建三個觀察者
person=Person()
bike=Bike()
car=Car()
# 將觀察者加入
light.join_observers(person)
light.join_observers(bike)
light.join_observers(car)
time.sleep(5)
# 將燈設(shè)置為綠色
light.set_color()
# 運(yùn)行結(jié)果
'''
加入觀察者
駐足等待
加入觀察者
駐足等待
加入觀察者
駐足等待
......等待5s后......
行人緩慢通行
自行車勻速通行
汽車快速通過
'''