觀察者模式【C#】

示例代碼爲了儘量突顯設計模式的特徵,採用了極簡代碼。儘可能避免其餘代碼對理解設計模式產生干擾

定義

定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。
簡而言之就是,觀察者模式能夠在被觀察者的某個指定動做執行時,通知到其對應的觀察者。使得觀察者們能夠即時作出相應的反應。

結構導圖

觀察者模式導圖


示例項目簡述

項目結構

示例代碼的大概意圖其實就是實現一個下載器。當指定文件下載完成後,會通知其觀察者們,以便這些觀察者能夠根據各自需求處理下載下來的文件。c#

接下來,請見具體代碼。設計模式

代碼

抽象觀察者

/// <summary>
/// 抽象觀察者
/// </summary>
interface IObserver
{
    void DoUpdate();
}

其實這個抽象觀察者,只是一個簡單的接口。全部具體觀察者都將繼承自它。spa

具體觀察者

/// <summary>
/// 具體觀察者-文件下載完成後,備份文件。
/// </summary>
class Observer1 : IObserver
{
    public void DoUpdate()
    {
        Console.WriteLine("觀察者1已將文件備份。");
    }
}

/// <summary>
/// 具體觀察者-文件下載完成後,壓縮文件。
/// </summary>
class Observer2 : IObserver
{
    public void DoUpdate()
    {
        Console.WriteLine("觀察者2已將文件壓縮。");
    }
}

/// <summary>
/// 具體觀察者-文件下載完成後,發送文件。
/// </summary>
class Observer3 : IObserver
{
    public void DoUpdate()
    {
        Console.WriteLine("觀察者3已將文件發送給相關同事。");
    }
}

以上是三個極簡的具體觀察者。它們分別在收到下載成功的通知後,對文件進行備份壓縮轉發設計

既然觀察者們已經準備好了,那麼該輪到被觀察者了。code

被觀察者

通常,被觀察者會相對複雜一點。由於它不僅僅要提供某動做的執行方法,也要提供註冊及註銷觀察者的方法。
當一個被觀察者被建立後,首先須要爲其綁定一些其必需的觀察者(若是須要的話)。觀察者們被綁定成功後,這個觀察者列表將被被觀察者維護着。
若被觀察者的某個動做執行完成後,若是須要通知觀察者,那麼就能夠經過這個觀察者列表,依次通知到全部須要被通知的觀察者。server

/// <summary>
/// 文件下載器-被觀察者
/// </summary>
class Downloader
{
    /// <summary>
    /// 觀察者列表
    /// </summary>
    public readonly HashSet<IObserver> observers;

    public Downloader()
    {
        observers = new HashSet<IObserver>();
    }

    /// <summary>
    /// 註冊觀察者
    /// </summary>
    public bool AddObserver(IObserver _observer)
    {
        return observers.Add(_observer);
    }

    /// <summary>
    /// 註銷觀察者
    /// </summary>
    public bool RemoveObserver(IObserver _observer)
    {
        return observers.Remove(_observer);
    }

    /// <summary>
    /// 下載
    /// </summary>
    public void Download()
    {
        Console.WriteLine("文件開始下載。");
        Console.WriteLine("文件下載中···");
        Thread.Sleep(3000);// 模擬文件下載的耗時過程
        Console.WriteLine("文件下載完成。");
        foreach (var observer in observers)
        {
            observer.DoUpdate();
        }
    }
}

如上代碼中,當Download方法內,文件下載成功後,就會遍歷觀察者列表,逐個通知對應的觀察者,告訴它們:文件下載成功了,你該幹嗎幹嗎去對象

客戶端

請看客戶端代碼blog

// 實例化下載器
var downloader = new Downloader();

// 建立觀察者
var o1 = new Observer1();
var o2 = new Observer2();
var o3 = new Observer3();

// 註冊觀察者
downloader.AddObserver(o1);
downloader.AddObserver(o2);
downloader.AddObserver(o3);

// 下載
downloader.Download();

建立一個被觀察者對象,而後爲其註冊三個觀察者。註冊成功後,就能夠執行下載文件的動做了。
當文件下載完成後,Download方法內部會自行通知已經成功註冊的觀察者們。繼承

運行結果

程序運行結果

如你所見,當文件下載完成的通知發出後,各個觀察者就開始了它們各自的小動做,分別是備份,壓縮,轉發。接口

總結

因爲觀察者們自己就有一個公共的抽象觀察者,這樣在某個觀察者須要變更時,大能夠廢棄掉這個觀察者,另起一個新的觀察者,而不用去對現有的任何觀察着作任何改動。所以從這個角度上講,觀察者模式是符合開閉原則的。
以上就是極簡版的觀察者模式的所有內容了。

相關文章
相關標籤/搜索