Design Pattern - Observer觀察者模式

Observer觀察者模式:

定義對象之間的一對多依賴關係,當一個對象更改狀態時,會自動通知其所有依賴的對象,也就是一個發佈者可以向多個事件的訂閱者發送訊息。

當多個 Class 都需要接收同一種資料的變化時,就適合使用 Observer Pattern。

上述「多個 Class 」指的就是「觀察者」,而「同一種資料」指的就是觀察者們想了解的「主題」,因此Observer Pattern實作的原理是將資料抽離出來,當資料改變時,同步發送給所有的觀察者。

internal class Program
{
    static void Main(string[] args)
    {
        // 商店被觀察者(發佈者)
        IPublisher shopPublisher = new ShopPublisher();

        // 觀察者(訂閱者)
        ISubscriber subscriber1 = new BuyerSubscriber("買家1號");
        ISubscriber subscriber2 = new BuyerSubscriber("買家2號");

        //訂閱商店
        shopPublisher.Attach(subscriber1);
        shopPublisher.Attach(subscriber2);

        // 設定新消息並通知所有觀察者
        shopPublisher.Publish("全店商品買一送一唷");
        Console.ReadLine();
    }
}

/// <summary>
/// 商店發佈者
/// </summary>
public class ShopPublisher : IPublisher
{
    private List<ISubscriber> subscribers = new List<ISubscriber>();
    private string message = "";

    public void Attach(ISubscriber observer)
    {
        subscribers.Add(observer);
    }

    public void Detach(ISubscriber observer)
    {
        subscribers.Remove(observer);
    }

    public void Notify()
    {
        foreach (var subscriber in subscribers)
        {
            subscriber.Update(message);
        }
    }
    public void Publish(string message)
    {
        this.message = message;
        Console.WriteLine($"發布訊息:{message}"); //紀錄發布訊息
        Notify(); //將訊息通知所有的訂閱者
    }
}

/// <summary>
/// 購買者(訂閱者)
/// </summary>
public class BuyerSubscriber : ISubscriber
{
    private string name = "";
    public BuyerSubscriber(string name)
    {
        this.name = name;
    }
    public void Update(string message)
    {
        Console.WriteLine($"{name} 收到訊息: {message}");
    }
}

/// <summary>
/// 被觀察者/發佈者
/// </summary>
public interface IPublisher
{
    /// <summary>訂閱</summary>
    void Attach(ISubscriber observer);

    /// <summary>取消訂閱</summary>
    void Detach(ISubscriber observer);

    /// <summary>通知所有訂閱者</summary>
    void Notify();

    /// <summary>發佈訊息</summary>
    void Publish(string message);
}

/// <summary>
/// 觀察者/訂閱者
/// </summary>
public interface ISubscriber
{
    void Update(string message);
}

參考資料:

https://medium.com/enjoy-life-enjoy-coding/design-pattern-%E5%8F%AA%E8%A6%81%E4%BD%A0%E6%83%B3%E7%9F%A5%E9%81%93-%E6%88%91%E5%B0%B1%E5%91%8A%E8%A8%B4%E4%BD%A0-%E8%A7%80%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F-observer-pattern-feat-typescript-8c15dcb21622