c# 實(shí)現(xiàn)觀察者模式
說(shuō)明:主要參考《Head First設(shè)計(jì)模式(中文版)》,使用C#代碼實(shí)現(xiàn)。
代碼:Github
1、觀察者模式UML圖

2、氣象監(jiān)測(cè)類(lèi)圖

3、氣象監(jiān)測(cè)代碼(書(shū)中C#版)
3.1 Observer
public interface IObserver
{
void Update(float temperature, float humidity, float pressure);
}
public interface IDisplayElement
{
void Display();
}
public class CurrentConditionDisplay : IObserver, IDisplayElement
{
private readonly ISubject _weatherData;
private float _temperature;
private float _humidity;
public CurrentConditionDisplay(ISubject weatherData)
{
_weatherData = weatherData;
_weatherData?.RegisterObserver(this);
}
public void Update(float temperature, float humidity, float pressure)
{
_temperature = temperature;
_humidity = humidity;
Display();
}
public void Display()
{
Console.WriteLine($"Current Conditions: {_temperature}F degress and {_humidity}% humidity");
}
}
3.2 Subject
public interface ISubject
{
void RegisterObserver(IObserver o);
void RemoveObserver(IObserver o);
void NotifyObservers();
}
public class WeatherData : ISubject
{
//觀察者列表
private readonly List<IObserver> _observerList;
//天氣數(shù)據(jù)
private float _temperature;
private float _humidity;
private float _pressure;
public WeatherData()
{
_observerList = new List<IObserver>();
}
/// <summary>
/// 訂閱觀察者
/// </summary>
/// <param name="o">觀察者對(duì)象</param>
public void RegisterObserver(IObserver o)
{
_observerList.Add(o);
}
/// <summary>
/// 移除觀察者
/// </summary>
/// <param name="o">觀察者對(duì)象</param>
public void RemoveObserver(IObserver o)
{
if (_observerList.Contains(o))
{
_observerList.Remove(o);
}
}
/// <summary>
/// 發(fā)布數(shù)據(jù)
/// </summary>
public void NotifyObservers()
{
foreach (var observer in _observerList)
{
observer.Update(_temperature, _humidity, _pressure);
}
}
/// <summary>
/// 數(shù)據(jù)發(fā)生改變
/// </summary>
private void MeasurementChanged()
{
NotifyObservers();
}
/// <summary>
/// 更新數(shù)據(jù)
/// </summary>
/// <param name="temperature">溫度</param>
/// <param name="humidity">濕度</param>
/// <param name="pressure">氣壓</param>
public void SetMeasurements(float temperature, float humidity, float pressure)
{
_temperature = temperature;
_humidity = humidity;
_pressure = pressure;
MeasurementChanged();
}
}
3.3 測(cè)試代碼
private static void TestWeatherData()
{
var weatherData = new WeatherData();
var currentConditionDisplay = new CurrentConditionDisplay(weatherData);
weatherData.SetMeasurements(80, 65, 30.4f);
weatherData.SetMeasurements(82, 70, 29.2f);
weatherData.SetMeasurements(78, 90, 29.2f);
}
4、使用C#中IObservable接口實(shí)現(xiàn)氣象監(jiān)測(cè)
4.1 輔助類(lèi)/結(jié)構(gòu)體
public struct WeatherMessage
{
public float Temperature { get; set; }
public float Humidity { get; set; }
public float Pressure { get; set; }
}
public class MessageUnknownException : Exception
{
internal MessageUnknownException()
{
}
}
4.2 IObserver具體實(shí)現(xiàn)
class CurrentConditionDisplayX : IObserver<WeatherMessage>, IDisplayElement
{
private IDisposable _unsubscribe;
private float _temperature;
private float _humidity;
public void Subscribe(IObservable<WeatherMessage> provider)
{
if (provider != null)
{
_unsubscribe = provider.Subscribe(this);
}
}
public void Unsubscribe()
{
_unsubscribe?.Dispose();
_unsubscribe = null;
}
public void OnCompleted()
{
Console.WriteLine("CurrentConditionDisplayX: OnCompleted");
Unsubscribe();
}
public void OnError(Exception error)
{
Console.WriteLine("CurrentConditionDisplayX: OnError");
}
public void OnNext(WeatherMessage value)
{
_temperature = value.Temperature;
_humidity = value.Humidity;
Display();
}
public void Display()
{
Console.WriteLine($"Current Conditions: {_temperature}F degress and {_humidity}% humidity");
}
}
4.3 IObservable具體實(shí)現(xiàn)
public class WeatherDataX : IObservable<WeatherMessage>
{
private readonly List<IObserver<WeatherMessage>> _observerList;
public WeatherDataX()
{
_observerList = new List<IObserver<WeatherMessage>>();
}
/// <summary>
/// 通知提供程序:某觀察程序?qū)⒁邮胀ㄖ?
/// </summary>
/// <param name="observer">要接收通知的對(duì)象。</param>
/// <returns>使資源釋放的觀察程序的接口。</returns>
public IDisposable Subscribe(IObserver<WeatherMessage> observer)
{
if(!_observerList.Contains(observer))
{
_observerList.Add(observer);
}
return new Unsubcriber(_observerList, observer);
}
public void SetMeasurements(Nullable<WeatherMessage> message)
{
foreach (var observer in _observerList)
{
if (!message.HasValue)
{
observer.OnError(new MessageUnknownException());
}
else
{
observer.OnNext(message.Value);
}
}
}
public void EndTransmission()
{
foreach (var observer in _observerList.ToArray())
{
if (_observerList.Contains(observer))
{
observer.OnCompleted();
}
}
_observerList.Clear();
}
private class Unsubcriber : IDisposable
{
private List<IObserver<WeatherMessage>> _observerList;
private IObserver<WeatherMessage> _observer;
public Unsubcriber(List<IObserver<WeatherMessage>> observerList, IObserver<WeatherMessage> observer)
{
_observerList = observerList;
_observer = observer;
}
public void Dispose()
{
if (_observerList != null && _observerList.Contains(_observer))
{
_observerList.Remove(_observer);
}
}
}
}
4.4 測(cè)試代碼
private static void TestWeatherDataX()
{
var weatherData = new WeatherDataX();
var currentConditionDisplay = new CurrentConditionDisplayX();
currentConditionDisplay.Subscribe(weatherData);
weatherData.SetMeasurements(new WeatherMessage()
{
Temperature = 80,
Humidity = 65,
Pressure = 30.4f
});
weatherData.SetMeasurements(new WeatherMessage()
{
Temperature = 82,
Humidity = 70,
Pressure = 29.2f
});
weatherData.SetMeasurements(new WeatherMessage()
{
Temperature = 78,
Humidity = 90,
Pressure = 29.2f
});
weatherData.EndTransmission();
}
以上就是c# 實(shí)現(xiàn)觀察者模式的詳細(xì)內(nèi)容,更多關(guān)于c# 觀察者模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析
這篇文章主要介紹了C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析,需要的朋友可以參考下2014-07-07
C#實(shí)現(xiàn)簡(jiǎn)單的汽車(chē)租賃系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)汽車(chē)租賃系統(tǒng)的具體實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
C#全局熱鍵設(shè)置與窗體熱鍵設(shè)置實(shí)例
這篇文章主要介紹了C#全局熱鍵設(shè)置與窗體熱鍵設(shè)置實(shí)例,對(duì)C#全局熱鍵設(shè)置與窗體熱鍵設(shè)置的實(shí)現(xiàn)方法與具體代碼進(jìn)行了詳細(xì)的介紹,需要的朋友可以參考下2014-10-10
C#WinFrom導(dǎo)出Excel過(guò)程解析
這篇文章主要介紹了C#WinFrom導(dǎo)出Excel過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
C#中的multipart/form-data提交文件和參數(shù)
這篇文章主要介紹了C#中的multipart/form-data提交文件和參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06

