Net設計模式實例之觀察者模式(Observer Pattern)

1、觀察者模式簡介(Brief Introduction

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象在狀態發生變化的時,會通知全部觀察者對象,使他們可以自動更新本身。 ide

2、解決的問題(What To Solve

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

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

3、觀察者模式分析(Analysis

1、觀察者模式結構

Subject:它把全部對觀察者對象的引用保存在一個彙集裏面,每一個主題均可以有任意數量的觀察者,抽象主題提供一個接口,能夠增長和刪除觀察者對象。 orm

public void Notify() server

{ 對象

    foreach(Observer o in observers) blog

    { 繼承

          o.Update(); 接口

    } 事件

ConcreteSubject具體的主題,將有關狀態存入具體觀察者對象,在具體主題的內部狀態改變時,給全部登記國的觀察者發出通知。

 

Observer:抽象觀察者,爲全部的具體觀察者定義一個接口,在獲得主題的通知時更新本身

ConcreteObserver:具體觀察者,實現抽象觀察者角色所要求的更新接口,以便使自己的狀態與主題的狀態相協調

2、源代碼

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

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);

    }

 

    /// <summary>

    /// 移除觀察者

    /// </summary>

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

    public void Detach(Observer observer)

    {

        observers.Remove(observer);

    }

 

    /// <summary>

    /// 通知觀察者

    /// </summary>

    public void Notify()

    {

        foreach (Observer o in observers)

        {

            o.Update();

        }

    }

}

 

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

public class ConcreteSubject:Subject

{

    private string _subjectState;

 

    /// <summary>

    /// 具體被觀察者狀態

    /// </summary>

    public string SubjectState

    {

        get { return _subjectState; }

        set { _subjectState = value; }

    }

}

 

3Observer抽象觀察者,爲全部的具體觀察者定義一個接口

public abstract class Observer

{

    public abstract void Update();

}

 

4ConcreteObserver具體觀察者

/// <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();

}

3、程序運行結果

四.觀察者實例分析(Example

1、場景

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

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

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

2、觀察者實例結構

       

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買入此股票

 

3、代碼

1Stock股票類

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>

    /// 添加觀察者

    /// </summary>

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

    public void AttachEvent(IObserver observer)

    {

        PriceChanged += new PriceChangedHandler(observer.Stoc_PriceChanged);

    }

}

 

2、事件參數StockDetailArgs

public class StockDetailArgsEventArgs

{

    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;

        }

    }

}

 

5、客戶端代碼

static void Main(string[] args)

{

    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();

    Console.Read();

}

 

4、程序運行結果

5、總結(Summary

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象在狀態發生變化的時,會通知全部觀察者對象,使他們可以自動更新本身。解決的是「當一個對象的改變須要同時改變其餘對象的時候」問題。

 

版權

做者:靈動生活

出處:http://www.cnblogs.com/ywqu

若是你認爲此文章有用,請點擊底端的【推薦】讓其餘人也瞭解此文章,

你也能夠加個人新浪微博,以便實時瞭解個人動態:http://weibo.com/ywqu

WOWO英語(英語培訓學校):http://www.wowomandarin.cn   上海電子商務解決方案:http://www.hello36.com 
上海閃酷系列解決方案: 
電子商務解決方案   移動電商APP軟件   培訓學校管理系統   購物分享社區系統   移動開發解決方案   在線問卷調查系統   

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。

相關文章
相關標籤/搜索