設(shè)計模式(二十一)觀察者模式(Observer)

觀察者.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后......

行人緩慢通行
自行車勻速通行
汽車快速通過
'''
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伞芹,一起剝皮案震驚了整個濱河市忘苛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唱较,老刑警劉巖扎唾,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異南缓,居然都是意外死亡胸遇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門汉形,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纸镊,“玉大人,你說我怎么就攤上這事概疆《和” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵岔冀,是天一觀的道長凯旭。 經(jīng)常有香客問我,道長使套,這世上最難降的妖魔是什么罐呼? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮侦高,結(jié)果婚禮上嫉柴,老公的妹妹穿的比我還像新娘。我一直安慰自己奉呛,他們只是感情好差凹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著侧馅,像睡著了一般危尿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馁痴,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天谊娇,我揣著相機(jī)與錄音,去河邊找鬼。 笑死济欢,一個胖子當(dāng)著我的面吹牛赠堵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播法褥,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼茫叭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了半等?” 一聲冷哼從身側(cè)響起揍愁,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杀饵,沒想到半個月后莽囤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡切距,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年朽缎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谜悟。...
    茶點(diǎn)故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡话肖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出葡幸,到底是詐尸還是另有隱情狼牺,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布礼患,位于F島的核電站是钥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缅叠。R本人自食惡果不足惜悄泥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肤粱。 院中可真熱鬧弹囚,春花似錦、人聲如沸领曼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庶骄。三九已至毁渗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間单刁,已是汗流浹背灸异。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肺樟。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓檐春,卻偏偏與公主長得像,于是被迫代替她去往敵國和親么伯。 傳聞我的和親對象是個殘疾皇子疟暖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容