設計模式筆記(11 OBSERVER & STATE)

OBSERVER(觀察者)
適用性:
1.當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這二者封裝在獨立的對象中以是他們可以各自獨立地改變和複用。
2.當對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象有待改變。
3.當一個對象必須通知其他對象,而他有不能假定其他對象是誰。

思考:
    考慮MVC架構的一個GUI場景,當一個模型對象改變,需要在多個View中及時的更新,而模型並不關心那個View需要獲取自己的數據。通過向模型對象註冊一個或者多個觀察者,每當模型發生變化的時候,就通知註冊的那些觀察者:模型更新了。這是觀察員模式的典型應用。有時候,我們可能並不希望直接在模型中實現註冊和發佈變更的能力,而是將這部分功能分離出去,這時,可以建立一個單一職責的發佈者類,發佈者負責接收訂閱和發佈更新,而模型一旦發生變化,只需要通知發佈者即可。也可以有Control層來協調模型的變化和通知發佈者的事宜。
   對於適用性的第一點,不理解應該是個什麼樣的組織形式。從我的猜測來看,這一點可能比較適合smalltalk而不是C++。
  從字面上理解, 第三點和第二點的區別只是在於被觀察對象和觀察員之間邏輯關係的區別。第二種情況似乎是被觀察對象和觀察員之間共同構成一個更大的高內聚的邏輯模塊。而第三種情況強調的僅僅是對象間需要發生消息傳遞。

STATE(狀態)
適用性:
1.一個對象的行爲取決於它的狀態,並且它必須在運行時刻根據狀態改變行爲。
2.一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。State模式將每一個條件分支放入一個獨立的類中。

思考:
    對於第一種情形,書中舉了個TCP連接的例子,把連接過程和讀取數據過程當作兩個不同的狀態。由State成員控制狀態的轉換,並且切換實際的工作單元。當然,這是一個巧妙的實現方式。不過,就TCP連接這件事情本身來說,封裝實現過程不如抽象實現過程。參考ACE的實現方法,是提供了一個Connector對象,並且運用工廠方法,連接成功生成Stream對象。這個抽象過程被衆多的網絡庫所採納,asio也採用這個抽象,據說asio要進boost了,真是個好消息。
    另外書中關於TCP的例子,我覺得更象是從switch演變過來的,這正是第二點的一個補充:即使是少量的分支,也是可以運用STATE模式的。
    在OO領域,switch一直以來是爲人詬病的:擴展極不靈活,代碼的遠程耦合。case 條件的設置和檢查是分離的,但是確是強耦合的。爲此,很多人建議使用表驅動的方式,這個表驅動其實只是一個跳轉表而已,好處是逼迫程序員必須將每個case的檢查分離到獨立的過程中去,不足是跳轉表仍然需要維護。如果把每個case的處理過程組織成class,在C++中,藉助局部靜態對象初始化技術,則有可能將跳轉表的維護半自動化,並且不再需要集中維護跳轉表。再考慮switch的工作過程:首先,我們要在某處設置case條件,然後最終落到swicth中去。既然我們需要設置case條件,那麼,另一個辦法是我們直接設置相應case條件的處理代碼,最後,在本來應該switch的地方調用我們設置的代碼就是了,這樣就徹底解決了switch。雖然,我們並不容易設置這樣一段代碼。但是,一般來說,還是比較容易的,最簡單的就是藉助於虛函數。爲處理代碼提供統一的接口,在選擇條件的地方,選擇合適的對象即可。另一個不錯的辦法則是使用functor。
    解決了switch,再來考慮設置條件的地方。如果選擇條件是一個複雜過程呢?我們連這個選擇過程也封裝起來,這樣一個運作方式就是state模式了。一個典型的複雜的選擇過程是狀態機。

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