Python與設計模式--觀察者模式

一、火警報警器

在門面模式中,我們提到過火警報警器。在當時,我們關注的是通過封裝減少代碼重複。而今天,我們將從業務流程的實現角度,來再次實現該火警報警器。

class AlarmSensor:
    def run(self):
        print "Alarm Ring..."
class WaterSprinker:
    def run(self):
        print "Spray Water..."
class EmergencyDialer:
    def run(self):
        print "Dial 119..."

以上是門面模式中的三個傳感器類的結構。仔細分析業務,報警器、灑水器、撥號器都是“觀察”煙霧傳感器的情況來做反應的。因而,他們三個都是觀察者,而煙霧傳感器則是被觀察對象了。根據分析,將三個類提取共性,泛化出“觀察者”類,並構造被觀察者。
觀察者如下:

class Observer:
    def update(self):
        pass
class AlarmSensor(Observer):
    def update(self,action):
        print "Alarm Got: %s" % action
        self.runAlarm()
    def runAlarm(self):
        print "Alarm Ring..."
class WaterSprinker(Observer):
    def update(self,action):
        print "Sprinker Got: %s" % action
        self.runSprinker()
    def runSprinker(self):
        print "Spray Water..."
class EmergencyDialer(Observer):
    def update(self,action):
        print "Dialer Got: %s"%action
        self.runDialer()
    def runDialer(self):
        print "Dial 119..."

觀察者中定義了update接口,如果被觀察者狀態比較多,或者每個具體的觀察者方法比較多,可以通過update傳參數進行更豐富的控制。
下面構造被觀察者。

class Observed:
    observers=[]
    action=""
    def addObserver(self,observer):
        self.observers.append(observer)
    def notifyAll(self):
        for obs in self.observers:
            obs.update(self.action)
class smokeSensor(Observed):
    def setAction(self,action):
        self.action=action
    def isFire(self):
        return True

被觀察者中首先將觀察對象加入到觀察者數組中,若發生情況,則通過notifyAll通知各觀察者。
業務代碼如下:

if __name__=="__main__":
    alarm=AlarmSensor()
    sprinker=WaterSprinker()
    dialer=EmergencyDialer()

    smoke_sensor=smokeSensor()
    smoke_sensor.addObserver(alarm)
    smoke_sensor.addObserver(sprinker)
    smoke_sensor.addObserver(dialer)


    if smoke_sensor.isFire():
        smoke_sensor.setAction("On Fire!")
        smoke_sensor.notifyAll()

打印如下:

Alarm Got: On Fire!
Alarm Ring...
Sprinker Got: On Fire!
Spray Water...
Dialer Got: On Fire!
Dial 119...

 

二、觀察者模式

觀察者模式也叫發佈-訂閱模式,其定義如下:定義對象間一種一對多的依賴關係,使得當該對象狀態改變時,所有依賴於它的對象都會得到通知,並被自動更新。
觀察者模式的通知方式可以通過直接調用等同步方式實現(如函數調用,HTTP接口調用等),也可以通過消息隊列異步調用(同步調用指被觀察者發佈消息後,必須等所有觀察者響應結束後纔可以進行接下來的操作;異步調用指被觀察者發佈消息後,即可進行接下來的操作。)。事實上,許多開源的消息隊列就直接支持發佈-訂閱模式,如Zero MQ等。

三、觀察者模式的優點和應用場景

優點:

1、觀察者與被觀察者之間是抽象耦合的;
2、可以將許多符合單一職責原則的模塊進行觸發,也可以很方便地實現廣播。

應用場景:

1、消息交換場景。如上述說到的消息隊列等;
2、多級觸發場景。比如支持中斷模式的場景中,一箇中斷即會引發一連串反應,就可以使用觀察者模式。

四、觀察者模式的缺點

1、觀察者模式可能會帶來整體系統效率的浪費;
2、如果被觀察者之間有依賴關係,其邏輯關係的梳理需要費些心思。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章