前言: 這篇文章我們以Head First設(shè)計(jì)模式中講解的氣象站為例,通過(guò)它的案列進(jìn)行學(xué)分析和編碼(C#)測(cè)試,并歸納總結(jié)出觀察者模式。

          1、氣象監(jiān)測(cè)案列,錯(cuò)誤示范實(shí)現(xiàn)


          一個(gè)氣象站,分別有三個(gè)裝置:溫度感應(yīng)裝置,濕度感應(yīng)裝置,氣壓感應(yīng)裝置。WeathData對(duì)象跟蹤氣象站數(shù)據(jù),WeathData有MeasurmentsChanged()方法,當(dāng)感應(yīng)裝置數(shù)據(jù)變化后就會(huì)調(diào)用MeasurmentsChanged對(duì)使用改數(shù)據(jù)的用戶進(jìn)行數(shù)據(jù)更新。目前需求是要三個(gè)布告板,分別是目前氣象數(shù)據(jù)狀況布告板(CurrentConditionDisply)、氣象數(shù)據(jù)統(tǒng)計(jì)布告板(StaisticsDisply)、天氣預(yù)報(bào)布告板(ForcastDisply)。三塊布告板都是需要接收氣象站數(shù)據(jù),然后按需展示到布告板上。針對(duì)這個(gè)需求我們可以如下方式實(shí)現(xiàn):
          public class WeatherData(){ private float Temperature{get;set;} private float
          Humidity{get;set;} private float Pressure{get;set;} public void
          MeasurmentsChanged(){
          CurrentConditionDisply.Update(Temperature,Humidity,Pressure);
          StaisticsDisply.Update(Temperature,Humidity,Pressure);
          ForcastDisply.Update(Temperature,Humidity,Pressure); } } public class
          CurrentConditionDisply{ public void Update(float temperature,float
          humidity,float Pressure){ //更新公布數(shù)據(jù) } } public class StaisticsDisply{ public
          void Update(float temperature,float humidity,float Pressure){ //更新統(tǒng)計(jì)數(shù)據(jù) } }
          public class ForcastDisply{ public void Update(float temperature,float
          humidity,float Pressure){ //更新天氣預(yù)報(bào) } }

          ?WeatherData是數(shù)據(jù)跟蹤對(duì)象,當(dāng)氣象站數(shù)據(jù)變化時(shí)用MeasurmentsChanged方法來(lái)依次調(diào)用三塊布告板的Update方法更新氣象數(shù)據(jù)。按照這種設(shè)計(jì)能實(shí)現(xiàn)目前需求,但是如果新加入一種布告板或者刪除一個(gè)布告板,那么我們需要去修改MeasurmentsChanged方法新增或者刪除代碼,這就會(huì)造成后期的維護(hù)擴(kuò)展問(wèn)題。這個(gè)例子暴露的問(wèn)題:

          1、我們是針對(duì)實(shí)現(xiàn)編程,而非針對(duì)接口。

          2、對(duì)于每個(gè)新的布告板,我們都得修改代碼。

          3、無(wú)法在運(yùn)行時(shí)動(dòng)態(tài)地增加或者刪除布告板。

          4、未封裝改變的部分,違反了對(duì)修改關(guān)閉,對(duì)擴(kuò)展開放原則。

          2、使用觀察者模式解耦

          由1的實(shí)現(xiàn)和帶來(lái)的問(wèn)題以及它的場(chǎng)景我們可以使用設(shè)計(jì)模式中的觀察者模式很好的滿足這一需求,且后面的維護(hù)擴(kuò)展都很方便。首先我們先了解觀察者模式

          觀察者模式:定義了對(duì)象之間的一對(duì)多依賴,當(dāng)一個(gè)對(duì)象改變時(shí),他的所有依賴都會(huì)收到通知并自動(dòng)更新。


          訂閱報(bào)紙就是典型的觀察者模式,出版社即為主題(subject),訂閱者即是觀察者(observer),當(dāng)有新報(bào)紙時(shí),報(bào)社就會(huì)派人送新報(bào)紙到訂閱了該報(bào)紙的讀者手上。我們通過(guò)觀察者模式類圖進(jìn)行理解我記憶,然后我們?cè)賹?duì)之前的氣象站進(jìn)行觀察者模式封裝修改。



          3、利用觀察者模式改進(jìn)氣象站


          按照觀察者模式我們需要定義一個(gè)主題接口Subject,WeatherData作為具體的主題類繼承接口Subject,實(shí)現(xiàn)注冊(cè)移除通知觀察者接口。定義Observer接口,其他三塊布告板繼承Observer實(shí)現(xiàn)自己的更新數(shù)據(jù)方法Update。
          /// <summary> /// 主題 /// </summary> public interface Subject { public void
          RegisterObserver(Observer o); public void RemoveObserver(Observer o); public
          void NotifyObserver(); } /// <summary> /// 具體主題(氣象站) /// </summary> public
          class WeatherData : Subject { private List<Observer> observers; private float
          Temperature { get; set; } private float Humidity { get; set; } private float
          Pressure { get; set; } public WeatherData() { observers = new List<Observer>();
          } public void RegisterObserver(Observer o) { observers.Add(o); } public void
          RemoveObserver(Observer o) { observers.Remove(o); } //通知觀察者 public void
          NotifyObserver() { foreach (var o in observers) { o.Update(Temperature,
          Humidity, Pressure); } } public void MeasurmentsChanged() { NotifyObserver(); }
          //數(shù)據(jù)變化 public void SetMeasurments(float temperature, float humidity, float
          pressure) { Temperature = temperature; Humidity = humidity; Pressure =
          pressure; MeasurmentsChanged(); } } /// <summary> /// 訂閱者 /// </summary> public
          interface Observer { void Update(float temperature, float humidity, float
          pressure); } public class CurrentConditionDisply : Observer { private Subject
          weatherData; public CurrentConditionDisply(Subject weatherData) {
          this.weatherData = weatherData; weatherData.RegisterObserver(this); } public
          void Update(float temperature, float humidity, float pressure) {
          Console.WriteLine($"當(dāng)前情況布告板:{temperature},{humidity},{pressure}"); } } public
          class StaisticsDisply : Observer { private Subject weatherData; public
          StaisticsDisply(Subject weatherData) { this.weatherData = weatherData;
          weatherData.RegisterObserver(this); } public void Update(float temperature,
          float humidity, float pressure) {
          Console.WriteLine($"統(tǒng)計(jì)數(shù)據(jù)布告板:{temperature},{humidity},{pressure}"); } } public
          class ForcastDisply : Observer { private Subject weatherData; public
          ForcastDisply(Subject weatherData) { this.weatherData = weatherData;
          weatherData.RegisterObserver(this); } public void Update(float temperature,
          float humidity, float pressure) {
          Console.WriteLine($"天氣預(yù)報(bào)布告板:{temperature},{humidity},{pressure}"); } }
          對(duì)使用了觀察者模式的氣象站進(jìn)行測(cè)試,當(dāng)數(shù)據(jù)變化的時(shí)候就會(huì)自動(dòng)通知觀察者并更新數(shù)據(jù),也可以靈活的添加移除觀察者而不用去具體的實(shí)現(xiàn)里面修改代碼。
          static void Main(string[] args) { WeatherData weatherData = new
          WeatherData(); CurrentConditionDisply currentConditionDisply = new
          CurrentConditionDisply(weatherData); StaisticsDisply staisticsDisply = new
          StaisticsDisply(weatherData); ForcastDisply forcastDisply = new
          ForcastDisply(weatherData); weatherData.SetMeasurments(30, 65, 30.5F);
          Console.WriteLine("---------------移除訂閱者-----------");
          weatherData.RemoveObserver(currentConditionDisply);
          weatherData.SetMeasurments(31,55,20);
          Console.WriteLine("---------------添加訂閱者-----------");
          weatherData.RegisterObserver(currentConditionDisply);
          weatherData.SetMeasurments(30, 55, 30.5F); Console.ReadKey(); }
            


          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問(wèn)題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                天天更新亚洲欧美成人 | 十种让男人爽到叫的方法 | 男性吹潮教程chinese视频 | 潮吹免费视频 | 韩日色逼|