接上文,既然乙個服務有多個消費者,在具體的功能實現上,會遇到許多有細微差別的地方,比如:
對商品的修改有些服務需要簡訊通知後台管理員,有些服務需要通過郵件+站內訊息的形式通知相關使用者,有些服務要求無需任何通知操作。
為了能相容這些矛盾,我們嘗試去新增相應的介面如下:
public inte***ce iorder
一旦需求有了新的變化,比如,有的服務要求編輯商品後傳送站內訊息+郵件,有的服務要求傳送簡訊+站內訊息+郵件等等,就需要新增新的介面。這就好像是求解一道功能之間排列組合的問題,n個功能的結果就是n的階乘。
我們現在選擇在介面設計時就把結果一一列出,宣告n的階乘個方法。一不小心就違反了單一職責原則、介面隔離原則和開閉原則。
造成這種尷尬局面的根本原因是:除了最基本的編輯之外,其他的諸如簡訊、郵件、站內訊息等附加功能是動態的,只有在呼叫時,才確定具體需要哪些附加功能。
是的,這裡並不需要保證資料強一致性,什麼簡訊、郵件、站內訊息都是事件驅動模型裡的東西,是非同步呼叫的,並不會阻塞訂單編輯操作,正是這些並不需要事務包裹的附加功能降低了模組的內聚。
基本思路:
方案1:不改變介面,而是建立乙個包裝物件,也就是裝飾來包裹真實的物件,動態的擴充套件乙個物件的功能=》裝飾器模式
方案2:業務邏輯層新增乙個訊息介面,直接把訊息傳送功能暴露給呼叫者,呼叫者自行決定何時何地呼叫。
zhe1)定義的訊息介面
public inte***ce imessage
public class smsbll:imessage
public class emailbll:imessage
public bool edit(string id,message entity)
return false;
}
觀察者模式(有時又被稱為模型-檢視(view)模式、源-收聽者(listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,乙個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。觀察者設計模式定義了物件間的一種一對多的組合關係,以便乙個物件的狀態發生變化時,所有依賴於它的物件都得到通知並執行。觀察者模式屬於行為型模式。
目標物件(isubject):訂單
觀察者(iobserver):簡訊、站內訊息、郵件
1)封裝觀察者:
//封裝訊息體
public class message
public string message
}//觀察者
public inte***ce iobserver
//簡訊觀察者
public class smsobserver:iobserver
}//站內訊息觀察者
public class messageobserver:iobserver
}。。。
2)建立目標物件介面,包括乙個觀察者佇列屬性和註冊觀察者、刪除觀察者、通知所有觀察者三個方法,並在訂單中實現目標物件介面:
public inte***ce isubject
//註冊
void registerobserver(iobserver o);
//刪除
void removeobserver(iobserver o);
//通知
void notifyobserver();
}public inte***ce iorder:isubject
//編輯
bool orderedit(order entity);
}public class orderbll:iorder
public void registerobserver(iobserver o)
}//刪除
public void removeobserver(iobserver o)
}//通知所有觀察者
public void notifyobserver(message entity)
}}
類中實現了註冊、刪除和通知方法,用以維護觀察者列表,基本滿足了我們的需求。
結構型設計模式是從程式的結構上解決模組之間的耦合問題,如裝飾器模式,在不改變原介面的情況下,通過新建立的類對原來的物件的進行擴充套件。而行為型設計模式是在不同物件之間劃分責任和演算法的抽象化,如觀察者模式,通過物件關聯的方式來分配多個職責。
我們在ioberserve這個介面中宣告了observers這個屬性,目的是保證主題實現類中的訊息列表屬性必須統一使用ilist型別,防止在不同的實現類裡出現諸如陣列、鍊錶、佇列、二叉樹等等五花八門的型別。
那就是說主題實現類中的觀察者列表是乙個屬性,是public型別,直接將這個列表暴露給了呼叫者,呼叫者可以直接操作訂單物件的observers屬性,例如可以通過操作list型別自帶的add方法來註冊,而不必通過類內部的實現的註冊方法,在訂單編輯之前,就可以通過遍歷該屬性就可以傳送訊息 。這破壞了類的封裝,減弱**的安全性。
我們需要對這個屬性欄位的進一步封裝,來約束呼叫者只能通過主題類內部實現的註冊、刪除和通知方法來操作observers屬性。
事件包含乙個私有的委託物件,只能在類內部觸發,封裝性和易用性特別好,這裡我們採用事件優化之前的**。
//訊息委託
public delegate void sendeventhandler(object sender, eventargs e);
//訂單
public inte***ce iorder:isubject
public class orderbll:iorder
}
事件限制了委託物件只能通過類內部的事件訪問器add和remove方法註冊和刪除,事件的廣播只能通過呼叫類內部的orderedit方法。
同一般的屬性,事件是也是通過事件訪問器來封裝的,非簡寫情況,**如下:
public class orderbll:iorder
}//刪除
remove}}
public bool orderedit(order entity)
}
可以發現,事件訪問器的add和remove方法都是void型別的。而屬性訪問器裡只有set方法是void型別,get方法有返回值,型別同欄位型別,這才是事件封裝性好的關鍵。 設計模式 十 觀察者模式
原理 又叫發布 訂閱模式,定義一種一對多的依賴,讓多個觀察者同時監聽某個主題物件,當該主題物件發生狀態變化時,通知所有已註冊的觀察者,使他們能夠自動更新自己例子 subject 抽象主題,它把所有對觀察者的物件引用儲存在乙個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供介面 attach d...
菜鳥學設計模式 觀察者模式
當物件存在一對多的關係時,則可以使用觀察者模式。最常見的就是當乙個物件被修改時,通知它的依賴物件。觀察者模式屬於行為型模式。整體介紹 意圖 定義物件間的一種一對多的依賴關係,當乙個物件的狀態發生改變的時候,所有依賴它的物件都得到通知並自動更新。主要解決 乙個物件狀態改變需要通知其他物件的問題,而且需...
python 設計模式 觀察者 觀察者設計模式
在觀察者設計模式這種模式中,物件被表示為等待事件觸發的觀察者。一旦發生指定的事件,觀察者就會關注該主體。當事件發生時,主體告訴觀察者它已經發生。以下uml圖表示觀察者模式 如何實現觀察者模式?現在讓我們來看看如何實現觀察者模式。參考以下實現 import threading import time ...