標籤:des style blog http color io ar 使用 for
前言
最近開始花點心思研究下設計模式,主要還是讓自己寫的代碼可重用性高、保證代碼可靠性。所謂設計模式,我找了下定義:是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編製真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。
為什麼要提倡“Design Pattern(設計模式)”?
根本原因是為了代碼複用,增加可維護性。因此這次我們來學習下設計模式,最後會通過C#語言來實現這些設計模式作為例子,深刻理解其中的精髓。
定義
觀察者模式,有時被稱作發布/訂閱模式,觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
特點
模式中具有的角色
1。 抽象主題(Subject):它把所有觀察者對象的引用儲存到一個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者對象。
2。 具體主題(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
3。抽象觀察者(Observer):為所有的具體觀察者定義一個介面,在得到主題通知時更新自己。
4。具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新介面,以便使本身的狀態與主題狀態協調。
·
優缺點
優點:
一、通知通訊
觀察者模式支援廣播通訊。被觀察者會向所有的註冊過的觀察者發出通知。
二、聚耦合
觀察者模式在被觀察者和觀察者之間建立了一個抽象的耦合,被觀察者並不知道任何一個具體的觀察者,只是儲存著抽象觀察者的列表,每個具體觀察者都符合一個抽象觀察者的介面。
缺點:
一、時間複雜度
如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
二、內聯不足
雖然觀察者模式可以隨時使觀察者知道所觀察的對象發送了變化,但是觀察者模式沒有相應的機制使觀察者知道所觀察的對象是怎樣發生變化的。
三、容易出現迴圈調用
如果在被觀察者之間有循環相依性的話,被觀察者會觸發它們之間進行迴圈調用,導致系統崩潰,在使用觀察者模式應特別注意這點。
實現思路
下面以xmfdsh發布一篇部落格的例子來說明觀察者模式的實現。關注了xmfdsh的朋友們,便可以通過觀察者模式來即時得到部落格進行了更新的資訊。當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面,將這兩者封裝在獨立的對象中以使它們可以各自獨立地改變和複用的情況下。從方面的這個詞中可以想到,觀察者模式肯定在AOP(面向方面編程)中有所體現。因此這種需求使用觀察者模式來解決就再恰當不過了。
觀察者向目標“訂閱”它的改變,而目標發生改變後就“通知”所有已經“訂閱”了它的改變的觀察者,從而執行“訂閱”的內容。這種機制的好處在於降低耦合度,分工明確,目標只負責在自身狀態發生改變或做出某種行為時向自身的訂閱清單發出“通知”,而不是直接調用觀察者的行為(方法);觀察者只負責向目標“訂閱”它的變化,以及定義自身在收到目標“通知”後所需要做出的具體行為(也就是訂閱的內容)
// 訂閱號抽象類別 public abstract class Blog { // 儲存訂閱者列表 private List<IObserver> observers = new List<IObserver>(); public string Symbol { get; set; }//描寫訂閱號的相關資訊 public string Info { get; set; }//描寫此次update的資訊 public Blog(string symbol, string info) { this.Symbol = symbol; this.Info = info; } // 對同一個訂閱號,新增和刪除訂閱者的操作 public void AddObserver(IObserver ob) { observers.Add(ob); } public void RemoveObserver(IObserver ob) { observers.Remove(ob); } public void Update() { // 遍曆訂閱者列表進行通知 foreach (IObserver ob in observers) { if (ob != null) { ob.Receive(this); } } } } // 具體訂閱號類 public class MyBlog : Blog { public MyBlog(string symbol, string info) : base(symbol, info) { } } // 訂閱者介面 public interface IObserver { void Receive(Blog tenxun); } // 具體的訂閱者類 public class Subscriber : IObserver { public string Name { get; set; } public Subscriber(string name) { this.Name = name; } public void Receive(Blog xmfdsh) { Console.WriteLine("訂閱者 {0} 觀察到了{1}{2}", Name, xmfdsh.Symbol, xmfdsh.Info); } } // 用戶端測試 class Program { static void Main(string[] args) { Blog xmfdsh = new MyBlog("xmfdsh", "發布了一篇新部落格"); // 添加訂閱者 xmfdsh.AddObserver(new Subscriber("王尼瑪")); xmfdsh.AddObserver(new Subscriber("唐馬儒")); xmfdsh.AddObserver(new Subscriber("王蜜桃")); xmfdsh.AddObserver(new Subscriber("敖尼瑪")); //更新資訊 xmfdsh.Update(); //輸出結果,此時所有的訂閱者都已經得到部落格的新訊息 Console.ReadLine(); } }
啟動並執行如下
此類實現方法的類圖如下:
這個類圖是visual studio產生的,可能看起來比較混亂把,這樣的實現就是觀察者模式的實現。任何時候,只要執行了Update方法,便會自動的去通知推送給訂閱了此訂閱號 的使用者,然而在C#中,我們更多的是使用委託與事件來簡化觀察者模式的實現。
class Program { // 委託充當訂閱者介面類 public delegate void NotifyEventHandler(object sender); // 抽象訂閱號類 public class Blog { public NotifyEventHandler NotifyEvent; public string Symbol { get; set; }//描寫訂閱號的相關資訊 public string Info { get; set; }//描寫此次update的資訊 public Blog(string symbol, string info) { this.Symbol = symbol; this.Info = info; } #region 新增對訂閱號列表的維護操作 public void AddObserver(NotifyEventHandler ob) { NotifyEvent += ob; } public void RemoveObserver(NotifyEventHandler ob) { NotifyEvent -= ob; } #endregion public void Update() { if (NotifyEvent != null) { NotifyEvent(this); } } } // 具體訂閱號類 public class MyBlog : Blog { public MyBlog(string symbol, string info) : base(symbol, info) { } } // 具體訂閱者類 public class Subscriber { public string Name { get; set; } public Subscriber(string name) { this.Name = name; } public void Receive(Object obj) { Blog xmfdsh = obj as Blog; if (xmfdsh != null) { Console.WriteLine("訂閱者 {0} 觀察到了{1}{2}", Name, xmfdsh.Symbol, xmfdsh.Info); } } } static void Main1(string[] args) { Blog xmfdsh = new MyBlog("xmfdsh", "發布了一篇新部落格"); Subscriber wnm = new Subscriber("王尼瑪"); Subscriber tmr = new Subscriber("唐馬儒"); Subscriber wmt = new Subscriber("王蜜桃"); Subscriber anm = new Subscriber("敖尼瑪"); // 添加訂閱者 xmfdsh.AddObserver(new NotifyEventHandler(wnm.Receive)); xmfdsh.AddObserver(new NotifyEventHandler(tmr.Receive)); xmfdsh.AddObserver(new NotifyEventHandler(wmt.Receive)); xmfdsh.AddObserver(new NotifyEventHandler(anm.Receive)); xmfdsh.Update(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("移除訂閱者王尼瑪"); xmfdsh.RemoveObserver(new NotifyEventHandler(wnm.Receive)); xmfdsh.Update(); Console.ReadLine(); } }
啟動並執行結果:
類圖:
總結
到這裡,觀察者模式就講完了,觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象可以同時監聽某一個主題對象,這個主題對象在發生狀態變化時,會通知所有觀察者對象,使它們能夠自動更新自己,因此在一些需求上是當一個對象的改變需要同時改變多個其他對象的時候,且不知道多少個對象需要去通知改變的時候,觀察者模式就成了首選,這種模式的用的最多的,在我的開發經曆中便是windows phone手機用戶端的開發了,經常要用到這類的委託事件的處理,用多了後發現就習以為常,這種模式也就沒那麼稀奇了。
源碼:http://files.cnblogs.com/xmfdsh/ConsoleApplication2.zip
C#設計模式-觀察者模式