在物件導向編程中,開發人員越來越注重以前的代碼的可重用性和可維護性。
設計模式使人們可以更加簡單方便地複用成功的設計和體繫結構。將已證實的技術表述成設計模式也會使新系統開發人員更加容易理解其設計思路。
今天我們來理解一下觀察者模式(Observer Patterns)。
觀察者模式屬於行為模式,是定義對象間的一種一對多的依賴關係,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動重新整理。它完美的將觀察者對象和被觀察者對象分離。可以在獨立的對象(主體)中維護一個對主體感興趣的依賴項(觀察器)列表。讓所有觀察器各自實現公用的 Observer 介面,以取消主體和依賴性對象之間的直接依賴關係。
例如,有一個郵局(Subject),下屬有數個業務員(Delegate),業務員下屬又有若干個郵遞員(Event),業務員和郵遞員之間是1:n的關係,郵遞員接受業務員的指示而決定把東西郵遞給誰。這樣,整個郵局就作為了一個被觀察者對象。又有一個雜誌社(Observer),為了將雜誌(Response方法)郵遞給訂閱者,必須通過郵局來辦理,於是雜誌社就找到了郵局的一個業務員,告訴他雜誌社要把這本雜誌郵遞給訂閱者,然後業務員把資訊轉達個他下屬的一個郵遞員,由郵遞員負責把雜誌送到指定的訂閱者手中。這就是一個典型的觀察者模式的例子,其中,郵局是被觀察者對象,雜誌社則為觀察者對象。
再來看另外一個例子,夜裡有一隻貓大叫了一聲,同處一屋的老鼠接受到了貓大叫的資訊,於是開始逃跑。同樣,主人聽到了,被吵醒了;小孩子聽到了,被嚇哭了。讓我們用代碼來實現這個例子。
首先,我們來建立觀察者模型。被觀察者對象可以定義一個抽象基類Subject,這個基類只負責定義委託和事件。
using System;
namespace DelegateEvent
{
/// <summary>
/// Subject 的摘要說明。
/// 被觀察者抽象基類
/// 所有被觀察者對象都繼承此類
/// 做為抽象基類,此類不允許直接進行執行個體化
/// 此類中首先定義委託
/// 再有委託定義事件
/// 然後創立與委託想關聯的方法Notify
/// </summary>
public abstract class Subject
{
public Subject()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
/// <summary>
/// 建立一個委託
/// </summary>
public delegate void SubEventHandler();
/// <summary>
/// 根據SubEventHandler建立一個事件
/// </summary>
public event SubEventHandler SubEvent;
/// <summary>
/// 將於委託相串連的方法
/// </summary>
protected void Notify()
{
if(this.SubEvent!=null)
this.SubEvent();
}
}
}
//------------------------------------------------------------------------------------------
被觀察者基類完成後我們再來建立觀察者基類Observer.
namespace DelegateEvent
{
/// <summary>
/// Observer 的摘要說明。
/// 觀察者抽象基類
/// 所有觀察者對象都由此類派生
/// 使用此類進行對事件的註冊
/// 並和事件的方法關聯
/// 另外定義了一個抽象方法Response
/// 可以由子類來進行覆蓋
/// </summary>
public abstract class Observer
{
public Observer(Subject childModel)
{
//註冊SubEvent事件通過SubEventHandler委託和Response方法關聯
//子類通過調用此建構函式完成事件的註冊
childModel.SubEvent+=new Subject.SubEventHandler(Response);
}
/// <summary>
/// 抽象方法,用於引發事件
/// </summary>
public abstract void Response();
}
}
同理,我們還可以繼續建立另一個觀察者基類,用來響應不同的事件的方法。
namespace DelegateEvent
{
/// <summary>
/// Observer2 的摘要說明。
/// 註冊了兩個事件的方法。
/// </summary>
public abstract class Observer2
{
public Observer2(Subject childModel)
{
childModel.SubEvent+=new Subject.SubEventHandler(Response);
childModel.SubEvent+=new Subject.SubEventHandler(Response2);
}
public abstract void Response();
public abstract void Response2();
}
}
//-------------------------------------------------------------------------------------------------------
現在,我們來針對這個執行個體中的貓大叫這個引發事件進行解析。
namespace DelegateEvent
{
/// <summary>
/// Cat 的摘要說明。
/// 此類作為被觀察者對象
/// 直接繼承Subject類
/// 使用一個Cry方法,調用Notify方法起用先前定義的SubEvent事件
/// </summary>
public class Cat:Subject
{
public Cat()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public void Cry()
{
System.Console.WriteLine("Cat Cry.....");
//調用從ModelBase繼承過來的Notify()
this.Notify();
}
}
}
// 這樣一個被觀察者對象就完成了。
***************************上面是被觀察者(被觀察都就是引發事件的),下面是觀察都**************************
//--------------------------------------------------------------------------------------------------------------------
被觀察者對象有了,我們再來建立具體的觀察者對象。此例中,有主人,小孩和老鼠對貓的叫聲做出了反應,因此我們可以建立三個類,分別對主人、小孩和老鼠進行響應。其中,主人和老鼠對應Observer類,響應其中的一個事件;而小孩則繼承Observer2類,響應其中的兩個事件。
//------------------------------------觀察者--主人類---------------------------------------------------
namespace DelegateEvent
{
/// <summary>
/// Master 的摘要說明。
/// </summary>
public class Master:Observer
{
/// <summary>
/// 建構函式,接受一個Cat類型的對象childModel並強制轉換為基類ModelBase變數
/// 再將childModel傳入到父類Observer的建構函式當中,實現註冊。
/// </summary>
/// <param name="childModel"></param>
public Master(Subject childModel):base(childModel)
{
}
public override void Response()
{
System.Console.WriteLine("主人醒來");
}
}
}
//------------------------------------觀察者--老鼠類-----------------------------------------------------
namespace DelegateEvent
{
/// <summary>
/// Mouse 的摘要說明。
/// </summary>
public class Mouse:Observer
{
private string name;
public Mouse(string name, Subject childModel):base(childModel)
{
this.name=name;
}
//覆蓋Observer類Response方法
public override void Response()
{
System.Console.WriteLine(this.name+"開始逃跑");
}
}
}
//於主人類不同的是,老鼠類的建構函式可以接受一個字串參數,這樣可以變的更多樣化
//------------------------------------觀察者--小孩------------------------------------------------------------
namespace DelegateEvent
{
/// <summary>
/// Child 的摘要說明。
/// </summary>
public class Child:Observer2
{
public Child(Subject childBase):base(childBase)
{
}
public override void Response()
{
Console.WriteLine("baby醒來。。。。");
}
public override void Response2()
{
Console.WriteLine("開始哭鬧。。。。。");
}
}
}
//小孩類裡,由於繼承的是Observer2類,因此可以響應兩種不同的方法。
在主函數裡,定義每個觀察者子類的對象,由其建構函式接受被觀察者對象進行事件的響應。
namespace DelegateEvent
{
/// <summary>
/// SubMain 的摘要說明。
/// </summary>
public class SubMain
{
public SubMain()
{
}
/// <summary>
/// 主函數,定義子類對象
/// </summary>
public static void Main()
{
Cat myCat=new Cat();
Mouse myMouse1=new Mouse("mouse1",myCat);
Mouse myMouse2=new Mouse("mouse2",myCat);
Master myMaster=new Master(myCat);
Child myLittleMaster=new Child(myCat);
myCat.Cry();
}
}
}
至此,一個簡單的觀察者模型結束了。