天天看點

Net設計模式執行個體之觀察者模式(Observer Pattern)

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象在狀态發生變化的時,會通知所有觀察者對象,使他們能夠自動更新自己。

當一個對象的改變需要同時改變其他對象的時候,而且不知道有多少對象有待改變時,應該考慮使用觀察者模式。

觀察者模式所做的工作其實就是解除耦合,讓耦合的雙方都依賴于抽象,而不是依賴于具體,進而使的各自的變化都不會影響另一邊的變化。

Net設計模式執行個體之觀察者模式(Observer Pattern)

public void Notify()

{

    foreach(Observer o in observers)

    {

          o.Update();

    }

ConcreteSubject類: 具體的主題,将有關狀态存入具體觀察者對象,在具體主題的内部狀态改變時,給所有登記國的觀察者發出通知。

Observer類:抽象觀察者,為所有的具體觀察者定義一個接口,在得到主題的通知時更新自己

ConcreteObserver:具體觀察者,實作抽象觀察者角色所要求的更新接口,以便使本身的狀态與主題的狀态相協調

1、Subject類,主題或者抽象通知者

public abstract class Subject

    private IList<Observer> observers = new List<Observer>();

    /// <summary>

    /// 添加觀察者

    /// </summary>

    /// <param name="observer">觀察者</param>

    public void Attach(Observer observer)

        observers.Add(observer);

    /// 移除觀察者

    public void Detach(Observer observer)

        observers.Remove(observer);

    /// 通知觀察者

    public void Notify()

        foreach (Observer o in observers)

        {

            o.Update();

        }

}

2、ConcreteSubject類,具體主題或者具體通知者

public class ConcreteSubject:Subject

    private string _subjectState;

    /// 具體被觀察者狀态

    public string SubjectState

        get { return _subjectState; }

        set { _subjectState = value; }

3、Observer抽象觀察者,為所有的具體觀察者定義一個接口

public abstract class Observer

    public abstract void Update();

4、ConcreteObserver具體觀察者

/// <summary>

/// 具體觀察者,實作抽象觀察者角色所要求的更新接口

/// 以便使本身的狀态與主題的狀态相協調

/// </summary>

public class ConcreteObserver:Observer

    private string name;

    private string observerState;

    private ConcreteSubject subject;

    public ConcreteSubject Subject

        get { return subject; }

        set { subject = value; }

    public ConcreteObserver(ConcreteSubject subject,string name)

        this.subject = subject;

        this.name = name;

    public override void Update()

        observerState = subject.SubjectState;

        Console.WriteLine("觀察者{0}的新狀态是{1}",name,observerState);

5、用戶端代碼

static void Main(string[] args)

    ConcreteSubject cs = new ConcreteSubject();

    cs.Attach(new ConcreteObserver(cs,"James"));

    cs.Attach(new ConcreteObserver(cs,"Jane"));

    cs.SubjectState="OK";

    cs.Notify();

    Console.Read();

Net設計模式執行個體之觀察者模式(Observer Pattern)

假設有一股票開盤價格16.50元,自從上市以來價格是不斷下降,而且以1.00元的速度下降。

在股票降到12.00元時,股民靈動生活買入了股票。

在股票降到8.05元時,股民Jane買了股票。

Net設計模式執行個體之觀察者模式(Observer Pattern)

Stock類,抽象通知者

定義了委托PriceChangedHandler ,調用了事件參數StockDetailsArgs 。

聲明了事件PriceChanged.

股票在下跌的過程中調用方法OnPriceChanged ,通過此方法觸發事件PriceChanged 。

AttachEvent 方法用來添加觀察者到對象。

StockDetailArgs類,事件參數繼承于EventArgs類,有樹形CurrentPrice用來專遞價格資料

接口IObserver和具體觀察者Observer類:

Stoc_PriceChanged方法:當股票在以1.00元降價的過程中調用此方法。當價格降到符合購買者價格,而且股票沒有被其他人購買的情況時,執行購買行為。

開盤價格:16.50

收盤價格:5.50

當價格降到12.00時,觀察者靈動生活買入此股票

當價格降到8.05時,觀察者Jane買入此股票

1、Stock股票類

public class Stock

    private double _openPrice;

    private double _closePrice;

    public delegate void PriceChangedHandler(object sender, StockDetailArgs e);

    public event PriceChangedHandler PriceChanged;

    public double OpenPrice

        get { return _openPrice; }

        set { _openPrice = value; }

    public double ClosePrice

        get { return _closePrice; }

        set { _closePrice = value; }

    public void StartTrading()

        double current;

        //Current price decrements by $1.00 as the stock is traded  

        current = OpenPrice;

        while (current > ClosePrice)

            //Stock is falling in increments of $1.00  

            current = current - 1.00;

            //Call the method to raise the event  

            OnPriceChanged(current);

            //Simulate a delay of 2000ms between market price updates  

            System.Threading.Thread.Sleep(2000);

    protected void OnPriceChanged(double currentMarketPrice)

        //Any handlers attached to this event?

        if (PriceChanged != null)

            StockDetailArgs args = new StockDetailArgs();

            args.CurrentPrice = currentMarketPrice;

            Console.WriteLine("目前股票價格是:" + args.CurrentPrice.ToString());

            ////Raise the event

            PriceChanged(this, args);

    /// </summary>

    public void AttachEvent(IObserver observer)

        PriceChanged += new PriceChangedHandler(observer.Stoc_PriceChanged);

2、事件參數StockDetailArgs

public class StockDetailArgs: EventArgs

    private double _currentPrice;

    public double CurrentPrice

        get { return _currentPrice; }

        set { _currentPrice = value; }

3、觀察者接口IObserver

public interface IObserver

    void Stoc_PriceChanged(object sender, StockDetailArgs e);

4、具體觀察者Observer

public class Observer : IObserver

    private string _investorName;

    private double _buyPrice;

    private Stock _stoc;

    private bool _hasBoughtStock = false;

    public string InvestorName

        get { return _investorName; }

        set { _investorName = value; }

    public double BuyPrice

        get { return _buyPrice; }

        set { _buyPrice = value; }

    public Stock Stoc

        get { return _stoc; }

        set { _stoc = value; }

    public Observer(string investorName, double buyPrice)

        this.InvestorName = investorName;

        this.BuyPrice = buyPrice;

    public void Stoc_PriceChanged(object sender, StockDetailArgs e)

        if (e.CurrentPrice <= BuyPrice && _hasBoughtStock == false)

            Console.WriteLine(string.Format("{0}在價格Price ={1}時買進了股票。",InvestorName,e.CurrentPrice));

            _hasBoughtStock = true;

    Stock stock = new Stock();

    stock.OpenPrice = 16.50;

    stock.ClosePrice = 5.50;

    Observer james = new Observer("靈動生活", 12.00);

    Observer jane = new Observer("jane",8.05);

    stock.AttachEvent(james);

    stock.AttachEvent(jane);

    stock.StartTrading();

Net設計模式執行個體之觀察者模式(Observer Pattern)

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象在狀态發生變化的時,會通知所有觀察者對象,使他們能夠自動更新自己。解決的是“當一個對象的改變需要同時改變其他對象的時候”問題。

版權

作者:靈動生活 郝憲玮

如果你認為此文章有用,請點選底端的【推薦】讓其他人也了解此文章,

Net設計模式執行個體之觀察者模式(Observer Pattern)

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

繼續閱讀