Python觀察者模式

[python|高級(jí)篇|筆記|設(shè)計(jì)模式|觀察者模式]


這兩天讀了[Head First設(shè)計(jì)模式][1]和[Python編程實(shí)戰(zhàn)][2]兩本書风喇,對(duì)設(shè)計(jì)模式終于有了那么一丟丟的體會(huì),在這里寫下來缕探,防止過兩天忘了魂莫。兩本一起讀的主要原因是因?yàn)槲覍?duì)java一竅不通。
HF里面對(duì)設(shè)計(jì)模式講的確實(shí)很通俗爹耗,按照他的說耙考,觀察者模式可以用報(bào)紙出版商和報(bào)紙訂閱者之間的關(guān)系來描述:
報(bào)社出版報(bào)紙谜喊,可以將它看做一個(gè)生產(chǎn)者,報(bào)紙訂閱者訂閱報(bào)紙倦始,可以將他看做一個(gè)個(gè)觀察者斗遏。
報(bào)社出版商可以提供以下的服務(wù):

  1. 注冊(cè)一個(gè)報(bào)紙訂閱者(Register)
  2. 注銷一個(gè)報(bào)紙訂閱者(Remove)
  3. 通知一個(gè)報(bào)紙訂閱者(Notify)

報(bào)紙訂閱者可以隨意定制自己,你是要拿報(bào)紙看楣号,還是鋪?zhàn)雷幼钜祝€是擦屁股隨你便

現(xiàn)在再來看觀察者模式的定義
定義了對(duì)象之間一對(duì)多依賴,當(dāng)一個(gè)對(duì)象改變狀態(tài)時(shí)炫狱,這個(gè)對(duì)象的所有依賴者都會(huì)收到通知并按照自己的方式進(jìn)行更新

按照HD上一個(gè)氣象站的例子來看觀察者模式
從氣象站取得數(shù)據(jù)后要在三個(gè)布告牌顯示這些數(shù)據(jù)藻懒,這三個(gè)布告牌顯示的內(nèi)容都不一樣,一塊實(shí)時(shí)顯示氣象數(shù)據(jù)视译,一塊顯示一段時(shí)間的統(tǒng)計(jì)數(shù)據(jù)嬉荆,一塊根據(jù)當(dāng)前數(shù)據(jù)顯示預(yù)測(cè)數(shù)據(jù),當(dāng)數(shù)據(jù)變化時(shí)酷含,這三個(gè)布告牌要按照自己的方式實(shí)時(shí)更新數(shù)據(jù)鄙早,例如,實(shí)時(shí)顯示布告牌就顯示當(dāng)前最新數(shù)據(jù)椅亚,統(tǒng)計(jì)數(shù)據(jù)布告牌將最大值最小值平均值顯示出來

先定義一個(gè)Observed類限番,這個(gè)類的作用類似于報(bào)紙出版商,他提供注冊(cè)呀舔,注銷弥虐,通知等功能

class Observed(object):
    def __init__(self):
    #此處初始化一個(gè)列表,里面裝滿了每一個(gè)觀察者
        self.__observers = []
    #注冊(cè)一個(gè)觀察者媚赖,注冊(cè)一個(gè)就往列表里添一個(gè)霜瘪,同時(shí)更新一下他的數(shù)據(jù)
    def registerObservers(self, observer):
        self.__observers.append(observer)
        observer.update(self)
    #注銷一個(gè)觀察者,誰不想看了惧磺,直接移走它颖对,以后數(shù)據(jù)更新了,跟他毛關(guān)系都沒了
    def romoveObserver(self, observer):
        self.__observers.remove(observer)
    #通知每一個(gè)觀察者磨隘,數(shù)據(jù)更新了缤底,你們?nèi)グ褦?shù)據(jù)整理整理在布告牌上發(fā)布吧
    def notifyObservers(self):
        for observer in self.__observers:
            observer.update(self)

定義一個(gè)WeatherModel類,這個(gè)類繼承字Observed類番捂,但是他提供采集數(shù)據(jù)的功能

#繼承了Observed類个唧,這樣它具有Observed類的數(shù)據(jù)及方法
class WeatherModel(Observed):
    #初始化時(shí),加入一些初始數(shù)據(jù)
    def __init__(self, temp, humidity, pressure):
        super(WeatherModel, self).__init__()
        self.temp = temp
        self.humidity = humidity
        self.pressure = pressure
    #增加一個(gè)valueChanged方法白嘁,當(dāng)數(shù)據(jù)改變時(shí),更新當(dāng)前數(shù)據(jù)膘流,然后通知每一個(gè)觀察者數(shù)據(jù)變了絮缅,要更新了
    def valueChanged(self, temp, humidity, pressure):
        if self.temp != temp or \
        self.humidity != humidity or \
        self.pressure != pressure:
            self.temp = temp
            self.humidity = humidity
            self.pressure = pressure
            self.notifyObservers()

定義兩個(gè)觀察者類鲁沥,CurrentCondition和StatisticCondition

#這個(gè)布告板顯示實(shí)時(shí)的氣象數(shù)據(jù)
class CurrentCondition(object):
    def __init__(self):
        self.currData = []
    #每一個(gè)觀察者都有一個(gè)update方法,Observed類里面的notifyObservers方法就是
    #使用每個(gè)觀察者各自的update方法更新數(shù)據(jù)耕魄,這個(gè)布告板里面的update方法是將三個(gè)氣象參數(shù)打成元組然后
    #放到初始化的currData列表里
    def update(self, model):
        self.currData.append((model.temp, model.humidity, model.pressure))
        
#這個(gè)布告板對(duì)氣象數(shù)據(jù)進(jìn)行統(tǒng)計(jì)
class StaticsCondition(object):
    #初始化了三個(gè)列表画恰,分別存放溫度,濕度和壓力吸奴,這樣方便統(tǒng)計(jì)最大值允扇,最小值和平均值
    def __init__(self):
        self.statDataHumidity = []
        self.statDataTemp = []
        self.statDataPressure = []
    #它的update方法是將每個(gè)參數(shù)放到各自的列表中去
    def update(self, model):
        self.statDataHumidity.append(model.humidity)
        self.statDataTemp.append(model.temp)
        self.statDataPressure.append(model.pressure)

之后,搞點(diǎn)數(shù)據(jù)測(cè)試一下

def main():
    #先創(chuàng)建兩個(gè)觀察者實(shí)例
    current = CurrentCondition()
    statistic = StaticsCondition()
    #創(chuàng)建一個(gè)模型實(shí)例则奥,傳入一些數(shù)
    model = WeatherModel(20.0, 55.0, 1013.11)
    #把這兩個(gè)觀察注冊(cè)一下考润,之后就可以給他們傳數(shù)據(jù)了
    model.registerObservers(current)
    model.registerObservers(statistic)
    #整點(diǎn)數(shù)據(jù),這里只是隨便寫寫读处,用于測(cè)試
    model.valueChanged(21.0, 52.3, 1013.12)
    model.valueChanged(21.2, 53.3, 1013.12)
    model.valueChanged(22.8, 56.1, 1013.18)
    #輸出每個(gè)觀察的數(shù)據(jù)列表
    print(current.currData)
    print(statistic.statDataTemp)
    print(statistic.statDataHumidity)
    print(statistic.statDataPressure)

輸出的結(jié)果

#currData列表里面是每一次數(shù)據(jù)變化時(shí)糊治,三個(gè)參數(shù)的實(shí)時(shí)變化列表,可以取出后再布告牌上顯示罚舱,
#當(dāng)然需要在CurrentCondition()里實(shí)現(xiàn)display方法才可以顯示
[(20.0, 55.0, 1013.11), (21.0, 52.3, 1013.12), (21.2, 53.3, 1013.12), (22.8, 56.1, 1013.18)]
#三個(gè)列表分別存放溫度井辜,濕度,氣壓參數(shù)管闷,可以在display方法里面按照時(shí)間統(tǒng)計(jì)一下
#平均值粥脚,最大值,最小值顯示在布告牌上
[20.0, 21.0, 21.2, 22.8]
[55.0, 52.3, 53.3, 56.1]
[1013.11, 1013.12, 1013.12, 1013.18]

這就是觀察者模式包个,說白了就是模型和視圖沒有關(guān)系刷允,有點(diǎn)像MVC啊。
[1]: http://item.jd.com/10100236.html
[2]: http://item.jd.com/11518115.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赃蛛,一起剝皮案震驚了整個(gè)濱河市恃锉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌呕臂,老刑警劉巖破托,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異歧蒋,居然都是意外死亡土砂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門谜洽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萝映,“玉大人,你說我怎么就攤上這事阐虚⌒虮郏” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奥秆。 經(jīng)常有香客問我逊彭,道長(zhǎng),這世上最難降的妖魔是什么构订? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任侮叮,我火速辦了婚禮,結(jié)果婚禮上悼瘾,老公的妹妹穿的比我還像新娘囊榜。我一直安慰自己,他們只是感情好亥宿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布卸勺。 她就那樣靜靜地躺著,像睡著了一般箩绍。 火紅的嫁衣襯著肌膚如雪孔庭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天材蛛,我揣著相機(jī)與錄音圆到,去河邊找鬼。 笑死卑吭,一個(gè)胖子當(dāng)著我的面吹牛芽淡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豆赏,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挣菲,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了掷邦?” 一聲冷哼從身側(cè)響起白胀,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抚岗,沒想到半個(gè)月后或杠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宣蔚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年向抢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胚委。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挟鸠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出亩冬,到底是詐尸還是另有隱情艘希,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站覆享,受9級(jí)特大地震影響鸠姨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淹真,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望连茧。 院中可真熱鬧核蘸,春花似錦、人聲如沸啸驯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽罚斗。三九已至徙鱼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間针姿,已是汗流浹背袱吆。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留距淫,地道東北人绞绒。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像榕暇,于是被迫代替她去往敵國(guó)和親蓬衡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • 本系列文章是希望將軟件項(xiàng)目中最常見的設(shè)計(jì)模式用通俗易懂的語言來講解清楚彤枢,并通過Python來實(shí)現(xiàn)狰晚,每個(gè)設(shè)計(jì)模式都是...
    geekpy閱讀 1,410評(píng)論 0 8
  • 1 場(chǎng)景問題# 1.1 訂閱報(bào)紙的過程## 來考慮實(shí)際生活中訂閱報(bào)紙的過程,這里簡(jiǎn)單總結(jié)了一下缴啡,訂閱報(bào)紙的基本流程...
    七寸知架構(gòu)閱讀 4,621評(píng)論 5 57
  • 目標(biāo):每一次天氣數(shù)據(jù)變化的時(shí)候壁晒,主顯示器更新數(shù)據(jù),溫度顯示器只顯示溫度數(shù)據(jù)盟猖,并且把歷史變化數(shù)據(jù)都展示出來讨衣。 思路:...
    ouyangbro閱讀 352評(píng)論 1 1
  • 觀察者模式,被觀察物自身屬性通知觀察者式镐。
    蝦想家閱讀 283評(píng)論 0 0
  • 在正式介紹觀察者模式前反镇,我們先引用生活中的小例子來模擬觀察者,先對(duì)觀察者模式有一個(gè)整體的感覺娘汞。 現(xiàn)實(shí)模擬 報(bào)紙和雜...
    六尺帳篷閱讀 1,643評(píng)論 6 18