1. 程式人生 > >設計模式(18)觀察者模式

設計模式(18)觀察者模式

模式介紹

觀察者模式試圖允許物件在其內部狀態改變時通知觀察者。

這意味著單個物件需要知道觀察它的物件,並且當狀態發生變化的時候,需要能夠與那些觀察者通訊。此外,觀察者應該被自動通知。

示例

設想我們需要一個系統來建模本地蔬菜市場中蔬菜價格的波動。
我們需要允許餐館檢視價格,並在特定蔬菜的價格低於指定閾值時下訂單,這對於每個餐館來說都是不同的。

抽象的蔬菜類:

/// <summary>
/// The Subject abstract class
/// </summary>
abstract class Veggies
{
    private double _pricePerPound;
    private List<IRestaurant> _restaurants = new List<IRestaurant>();

    public Veggies(double pricePerPound)
    {
        _pricePerPound = pricePerPound;
    }

    public void Attach(IRestaurant restaurant)
    {
        _restaurants.Add(restaurant);
    }

    public void Detach(IRestaurant restaurant)
    {
        _restaurants.Remove(restaurant);
    }

    public void Notify()
    {
        foreach (IRestaurant restaurant in _restaurants)
        {
            restaurant.Update(this);
        }

        Console.WriteLine("");
    }

    public double PricePerPound
    {
        get { return _pricePerPound; }
        set
        {
            if (_pricePerPound != value)
            {
                _pricePerPound = value;
                Notify(); //Automatically notify our observers of price changes
            }
        }
    }
}

具體的蔬菜類-胡蘿蔔:

/// <summary>
/// The ConcreteSubject class
/// </summary>
class Carrots : Veggies
{
    public Carrots(double price) : base(price) { }
}

抽象的餐館:

/// <summary>
/// The Observer interface
/// </summary>
interface IRestaurant
{
    void Update(Veggies veggies);
}

具體的餐館:

/// <summary>
/// The ConcreteObserver class
/// </summary>
class Restaurant : IRestaurant
{
    private string _name;
    private Veggies _veggie;
    private double _purchaseThreshold;

    public Restaurant(string name, double purchaseThreshold)
    {
        _name = name;
        _purchaseThreshold = purchaseThreshold;
    }

    public void Update(Veggies veggie)
    {
        Console.WriteLine("Notified {0} of {1}'s " + " price change to {2:C} per pound.", _name, veggie.GetType().Name, veggie.PricePerPound);
        if(veggie.PricePerPound < _purchaseThreshold)
        {
            Console.WriteLine(_name + " wants to buy some " + veggie.GetType().Name + "!");
        }
    }
}

客戶端呼叫:

static void Main(string[] args)
{
    // Create price watch for Carrots and attach restaurants that buy carrots from suppliers.
    Carrots carrots = new Carrots(0.82);
    carrots.Attach(new Restaurant("Mackay's", 0.77));
    carrots.Attach(new Restaurant("Johnny's Sports Bar", 0.74));
    carrots.Attach(new Restaurant("Salad Kingdom", 0.75));

    // Fluctuating carrot prices will notify subscribing restaurants.
    carrots.PricePerPound = 0.79;
    carrots.PricePerPound = 0.76;
    carrots.PricePerPound = 0.74;
    carrots.PricePerPound = 0.81;

    Console.ReadKey();
}

總結

觀察者模式是常用的設計模式之一,簡單來說就是,如果主體改變了,觀察者需要知道它。

原始碼

https://github.com/exceptionnotfound/DesignPatterns/tree/master/Observer

原文

https://www.exceptionnotfound.net/the-daily-design-pattern-observer/