close

觀察者模式定義: 有一個主題大家去訂閱他,當主題資訊更新時候,會一起發送資訊給所有觀察者。

在此範例中,主題是一介面,WeatherData class會實做此主題介面用以設定値實做其方法(讓訂閱者註冊移除等等),

CurrentConditionDisplay就是一個訂閱者,每個訂閱者都可以有自己的Update方法顯示不同資訊,

每當主題有更新資訊時候,就會把資訊傳到各個訂閱者,訂閱者再依照此數値取計算顯示自己規格的資訊。

好處是:當要規格修改時,只需要修改主題(或出版者),其他觀察者(或訂閱者)不需要更動,以此減少程式碼為護修改錯誤的風險。

 

用到技術觀念: 

a.多個class 實做同個 Interface,以此達到多型。

b.封裝

 

1.ISubject.cs

//主題介面
//1.給觀察者註冊
//2.移除觀察者
//3.通知所有觀察者
public interface ISubject
{
void RegisterObserver(IObserver o);
void RemoveObserver(IObserver o);
void NotifyObserver();
}

 

2.IObserver.cs

//觀察者(或訂閱者)介面:所有觀察者都必須實做,以實踐update(),觀察者指的就是佈告欄
public interface IObserver
{
//當氣象數據改變時候,主題會把這些數據傳給觀察者
void Update(float temperature, float humidity, float pressure);
}

 

3.IDisplayElement.cs

//所有佈告欄都必須實做此方法

//當佈告欄需要顯示資料時,呼叫此方法
public interface IDisplayElement
{
object Display();
}

 

4.WeatherData.cs

//WeatherData會去實做主題介面(ISubject.cs)

public class WeatherData : ISubject
{
private ArrayList observers; //存放觀察者的陣列
private float temperature;
private float humidity;
private float pressure;

//建構子,建立ArryaList存放觀察者陣列
public WeatherData()
{
observers = new ArrayList();
}

//觀察者註冊方法實做
public void RegisterObserver(IObserver o)
{
//將傳入的觀察者物件加入ArrayList(observers)中
observers.Add(o);
}

//觀察者移除方法實做
public void RemoveObserver(IObserver o)
{
//將傳入的觀察者物件從ArrayList(observers)中移除
observers.Remove(o);
}

//通知觀察者方法實做
//通知每一個觀察者,因為觀察者都實做了IObserver介面,所以一定會實做Update()方法
public void NotifyObserver()
{
//進去observers(List)裡面繞行,看有幾個觀察者,觀察者就是佈告欄可能會有多個
foreach (IObserver observer in observers)
{
//更新資料方法,在CurrentConditionsDisplay class下就是去重新設定値
//這段特別注意,不同訂閱者(不同佈告欄)有不同的Update方法,因為都有實做IObserver,所以會去呼叫不同佈告欄之方法
//就是多個類別(佈告欄)實做同一介面(IObserver),之後呼叫方法只需要寫介面的型別,就會去呼叫正確方法。
//不過主要是aspx.cs檔案那邊,是新增CurrentConditionsDisplay class的物件,所以他會知道要去呼叫哪一個佈告欄的Update()
observer.Update(temperature, humidity, pressure);
}
}

//當氣象局有更新數據時,通知觀察者
public void MeasurementsChanged()
{
//呼叫此方法更新資料並去通知每一個觀察者
NotifyObserver();
}

//設定氣象溫度溼度...
public void SetMeasurements(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
//數據有更新,呼叫此方法通知觀察者
MeasurementsChanged();
}
}

 

5.CurrentConditionDisplay.cs(不同的佈告欄,這是多個佈告欄其中之一,每個佈告欄有自己的顯示方式以及計算方式)

//佈告欄實做介面
//有實做IObserver介面,所以可以WeatherData取得異動
public class CurrentConditionsDisplay : IObserver, IDisplayElement
{
private float temperature;
private float humidity;
private float pressure;
private ISubject weatherData;

//建構子,一建立物件就去註冊
public CurrentConditionsDisplay(ISubject weatherData)
{
this.weatherData = weatherData;
weatherData.RegisterObserver(this);

}

public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
}

public object Display()
{
return "Current conditions: " + temperature + "F degrees and " + humidity + "% humidity";
}
}

 

6.網頁檔

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string Result;//用來接收更新後的佈告欄回傳值

WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.SetMeasurements(180, 65, 30.4F);//進去更新値,會觸發一系列設定値以及通知等動作
Result = currentDisplay.Display().ToString();
Response.Write(Result);
}
}

 

arrow
arrow
    文章標籤
    觀察者
    全站熱搜
    創作者介紹
    創作者 melomelo1988 的頭像
    melomelo1988

    melo 唐

    melomelo1988 發表在 痞客邦 留言(0) 人氣()