自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解析.NET觀察者模式(Observer Pattern)

開發(fā) 架構(gòu)
觀察者模式是一種設(shè)計(jì)模式。設(shè)計(jì)模式是面向?qū)ο笏枷氲募蟪?,GOF在其經(jīng)典著作中總結(jié)了23種設(shè)計(jì)模式,又可分為:創(chuàng)建型、結(jié)構(gòu)型和行為型3個(gè)大類,其中觀察者模式屬于行為型模式。

概要

觀察者模式是一種設(shè)計(jì)模式。設(shè)計(jì)模式是面向?qū)ο笏枷氲募蟪?,GOF在其經(jīng)典著作中總結(jié)了23種設(shè)計(jì)模式,又可分為:創(chuàng)建型、結(jié)構(gòu)型和行為型3個(gè)大類,其中觀察者模式屬于行為型模式。

目錄 

觀察者模式定義

實(shí)現(xiàn)觀察者模式的過程

觀察者模式結(jié)構(gòu)

觀察者模式實(shí)例

觀察者模式總結(jié)

一、觀察者模式定義

1.觀察者模式定義了對象間的一對多依賴關(guān)系。當(dāng)一方的對象改變狀態(tài)時(shí),所有的依賴者都會(huì)被通知并自動(dòng)被更新。

2.在觀察者模式中,被依賴的一方叫做目標(biāo)或主題(Subject),依賴方叫做觀察者(Observers)。

二、實(shí)現(xiàn)觀察者模式的過程  

實(shí)現(xiàn)觀察者模式有很多形式,比較直觀的是使用一種“注冊--通知--撤銷注冊”的形式。下面的三個(gè)圖詳細(xì)的描述了這樣一種過程:

1.觀察者

(Observer)將自己注冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個(gè)容器(Container)里。

圖一

2.被觀察對象

被觀察對象發(fā)生了某種變化(如圖中的SomeChange),從容器中得到所有注冊過的觀察者,將變化通知觀察者。

圖二

3.撤銷觀察

觀察者告訴被觀察者要撤銷觀察,被觀察者從容器中將觀察者去除。

圖三

觀察者將自己注冊到被觀察者的容器中時(shí),被觀察者不應(yīng)該過問觀察者的具體類型,而是應(yīng)該使用觀察者的接口。這樣的優(yōu)點(diǎn)是:假定程序中還有別的觀察者,那么只要這個(gè)觀察者也是相同的接口實(shí)現(xiàn)即可。一個(gè)被觀察者可以對應(yīng)多個(gè)觀察者,當(dāng)被觀察者發(fā)生變化的時(shí)候,他可以將消息一一通知給所有的觀察者?;诮涌冢皇蔷唧w的實(shí)現(xiàn)——這一點(diǎn)為程序提供了更大的靈活性。

#p#

三、觀察者模式結(jié)構(gòu)

觀察者模式是對象的行為型模式,又叫做發(fā)表-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-收聽者(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式結(jié)構(gòu)類圖如下:

圖四

1.Subject(主題接口)  

1.1規(guī)定ConcreteSubject的統(tǒng)一接口;

1.2每個(gè)Subject可以有多個(gè)Observer;

2.ConcreteSubject(具體主題)

2.1維護(hù)對所有具體觀察者的引用的列表;

2.2狀態(tài)發(fā)生變化時(shí)會(huì)發(fā)送通知給所有注冊的觀察者。

3.Observer(觀察者接口)

3.1規(guī)定ConcreteObserver的統(tǒng)一接口;

3.2定義了一個(gè)update()方法,在被觀察對象狀態(tài)改變時(shí)會(huì)被調(diào)用。

4.ConcreteObserver(具體觀察者)

4.1維護(hù)一個(gè)對ConcreteSubject的引用;

4.2特定狀態(tài)與ConcreteSubject同步;

4.3實(shí)現(xiàn)Observer接口,通過update()方法接收ConcreteSubject的通知。

四、觀察者模式實(shí)例

在之前,Bohan向我們分享了一個(gè)關(guān)于開發(fā)下一代基于因特網(wǎng)的天氣監(jiān)測系統(tǒng)的實(shí)例。該監(jiān)測系統(tǒng)涉及到的參數(shù)一共有三種:temperature, humidity, pressure,外界接受到的信息也以三種布告板顯示:currentConditionDisplay會(huì)列出當(dāng)前的氣溫,濕度和氣壓;statisticsDisplay會(huì)列出當(dāng)前的溫度最高,最低和平均值;forecastDisplay列出將來預(yù)測的天氣狀況。

1.普通實(shí)現(xiàn)方法

現(xiàn)在我們用最容易想到的一個(gè)方法來實(shí)現(xiàn)系統(tǒng):

  1. 天氣檢測系統(tǒng)普通做法  
  2.  Public  class WeatherData {  
  3.  //聲明實(shí)例變量…   
  4.  Public void measurementsChanged(){  
  5.      float temp=getTemperature();  
  6.      float humidity = getHumidity();  
  7.      float pressure=getPressure();  
  8.     currentConditionDisplay.update(temp,humidity,pressure);  
  9.      statisticsDisplay.update(temp,humidity,pressure);  
  10.      forecastDisplay.update(temp,humidity,pressure);  
  11.              }  
  12.  } 

的確,該方法可以實(shí)現(xiàn)這個(gè)系統(tǒng),但是仔細(xì)想想面向?qū)ο蟮脑O(shè)計(jì)原則就知道這種實(shí)現(xiàn)是有問題的:

  1. currentConditionDisplay.update(temp,humidity,pressure);  
  2. statisticsDisplay.update(temp,humidity,pressure);  
  3. forecastDisplay.update(temp,humidity,pressure); 

這里違背了“面向接口編程,而不要面向?qū)崿F(xiàn)編程”的原則,會(huì)使我們在增加或刪除不同的布告板時(shí)必須修改程序。也就是說,布告板相關(guān)的部分是系統(tǒng)中最不穩(wěn)定的部分,應(yīng)該將其單獨(dú)隔離開。針對這個(gè)問題,我們可以想到曾經(jīng)學(xué)過的另一個(gè)原則:“找到系統(tǒng)中變化的部分,將變化的部分同其它穩(wěn)定的部分隔開”。因此,我們將使用觀察者模式來實(shí)現(xiàn)該天氣監(jiān)測系統(tǒng)。

2.觀察者模式實(shí)現(xiàn)方法

就天氣監(jiān)測系統(tǒng)問題的應(yīng)用場景來說,WeatherData可以作為ConcreteSubject(具體主題)來看待,而不同的布告板(currentConditionDisplay、statisticsDisplay、forecastDisplay)則可以作為ConcreteObserver(具體觀察者)來看待,也就是說布告板觀察WeatherData對象,如果WeatherData對象有任何狀態(tài)變化,則立刻更新布告板的數(shù)據(jù)信息。 下面是詳細(xì)的代碼實(shí)現(xiàn):

2.1主題接口ISubject.cs:

  1. public interface ISubject  
  2.       {  
  3.           void RegisterObserver(IObserver o);  
  4.          void RemoveObserver(IObserver o);  
  5.           void NotifyObserver();  
  6.       } 

2.2觀察者接口IObserver.cs:

  1. public interface IObserver  
  2.      {       //給update()方法定義了三個(gè)對應(yīng)不同氣象數(shù)據(jù)的參數(shù)。  
  3.           void Update(float temperature, float humidity, float pressure);  
  4.       } 

2.3用于顯示結(jié)果的接口IDisplayElement.cs:

  1. public interface IDisplayElement  
  2.       {  
  3.          void  Display();  
  4.        } 

2.4具體主題WeatherData.cs:

這個(gè)類是ISubject的具體實(shí)現(xiàn),內(nèi)部使用ArrayList來記錄所有注冊的觀察者,SetMeasurements() 方法是用來模擬在天氣狀況改變的時(shí)候自動(dòng)觸發(fā)MeasurementsChanged()方法的機(jī)制。

  1. 具體主題WeatherData  
  2.  public class WeatherData : ISubject  
  3.       {  
  4.           private ArrayList observers;  
  5.           private float temperature;  
  6.           private float humidity;  
  7.           private float pressure;  
  8.    
  9.          public WeatherData()  
  10.          {  
  11.              observers = new ArrayList();  
  12.          }  
  13.        #region  ISubject Members    
  14.             //注冊觀察者  
  15.          public void RegisterObserver(IObserver o)  
  16.          {  
  17.              observers.Add(o);  
  18.          }  
  19.           //移除觀察者  
  20.          public void RemoveObserver(IObserver o)  
  21.          {  
  22.              int i = observers.IndexOf(o);  
  23.              if(i >= 0)  
  24.              {  
  25.                  observers.Remove(o);  
  26.              }  
  27.          }  
  28.           //通知所有觀察者  
  29.          public void NotifyObserver()  
  30.          {  
  31.              foreach(IObserver observer in observers)  
  32.              {  
  33.                  observer.Update(temperature,humidity,pressure);  
  34.              }  
  35.          }  
  36.        #endregion  
  37.          public void MeasurementsChanged()  
  38.          {       //更新數(shù)據(jù)  
  39.              NotifyObserver();  
  40.          }  
  41.          public void SetMeasurements(float temperature, float humidity,float pressure)  
  42.          {  
  43.              this.temperature = temperature;  
  44.              this.humidity = humidity;  
  45.              this.pressure = pressure;  
  46.              MeasurementsChanged();  
  47.          }  
  48.      } 

#p#

2.5具體觀察者:

  • CurrentConditionsDisplay.cs:

這個(gè)類是IObserver和IDisplayElement的具體實(shí)現(xiàn),代表顯示當(dāng)前天氣狀況的具體布告板對象,其內(nèi)部維護(hù)了一個(gè)ISubject類型的變量,該變量在CurrentConditionsDisplay的構(gòu)造函數(shù)中被初始化,同時(shí)調(diào)用ISubject.registerObserver()方法,實(shí)現(xiàn)訂閱ISubject。

  1. CurrentConditionsDisplay   
  2.  public class CurrentConditionsDisplay :IObserver, IDisplayElement  
  3.        {  
  4.            private float temperature;  
  5.            private float humidity;  
  6.            private float pressure;  
  7.           private ISubject weatherData;  
  8.     
  9.           public CurrentConditionsDisplay(ISubject weatherData)  
  10.           {  
  11.               this.weatherData = weatherData;  
  12.               weatherData.RegisterObserver(this);  
  13.           }  
  14.        #region IObserver Members  
  15.       public void Update(float temperature, float humidity, float pressure)  
  16.           {  
  17.                //獲取更新的溫度數(shù)據(jù)  
  18.                //獲取更新的濕度數(shù)據(jù)  
  19.                //獲得更新的氣壓數(shù)據(jù)  
  20.               this.temperature = temperature;  
  21.               this.humidity = humidity;  
  22.               this.pressure = pressure;  
  23.              Display();  
  24.          }  
  25.           #endregion  
  26.      #region IDisplayElement Members  
  27.        public void Display()   //顯示當(dāng)前觀測值  
  28.           {  
  29.               Console.WriteLine( "Current conditions: " + temperature +"F degrees and " + humidity + "% humidity and "+pressure+"f pressure");  
  30.           }  
  31.           #endregion  
  32.       } 
  • ForcastDisplay.cs:
  1. ForcastDisplay   
  2.   public class ForcastDisplay : IObserver, IDisplayElement  
  3.      {   //顯示預(yù)測的天氣預(yù)報(bào)的觀察者  
  4.          private float currentPressure = 30.2f;  
  5.          private float lastPressure;  
  6.          private ISubject weatherData;  
  7.    
  8.          public ForcastDisplay(ISubject weatherData)  
  9.          {  
  10.              this.weatherData = weatherData;  
  11.              weatherData.RegisterObserver(this);  
  12.          }  
  13.          #region IObserver Members  
  14.          // 獲取更新的氣壓數(shù)據(jù)  
  15.          public void Update(float temperature, float humidity, float pressure)  
  16.          {  
  17.              lastPressure = currentPressure;  
  18.              currentPressure = pressure;  
  19.              Display();  
  20.          }  
  21.          #endregion  
  22.          #region IDisplayElement Members  
  23.           //顯示預(yù)測的天氣預(yù)報(bào)  
  24.          public void Display()        
  25.          {  
  26.              StringBuilder sb = new StringBuilder();  
  27.              sb.Append("Forecast: ");  
  28.    
  29.              if (currentPressure > lastPressure)  
  30.              {  
  31.                  sb.Append("Improving weather on the way!");  
  32.              }  
  33.              else if (currentPressure == lastPressure)  
  34.              {  
  35.                  sb.Append("More of the same");  
  36.              }  
  37.              else if (currentPressure < lastPressure)  
  38.              {  
  39.                  sb.Append("Watch out for cooler, rainy weather");  
  40.              }  
  41.              Console.WriteLine(sb.ToString());  
  42.          }  
  43.          #endregion  
  44.      } 
  • StatisticsDisplay.cs:
  1. StatisticsDisplay  
  2.     public class StatisticsDisplay : IObserver, IDisplayElement  
  3.        {  
  4.              //顯示平均、最大、最小觀測值的觀察者  
  5.         //F為華氏溫度,攝氏=5/9(F-32)  
  6.             #region Members  
  7.            private float maxTemp = 0.0f;  
  8.           private float minTemp = 200;                                      
  9.           private float temperatureSum = 0.0f;  
  10.           private int numReadings = 0;  
  11.           private ISubject weatherData;  
  12.           #endregion//Members  
  13.          #region NumberOfReadings Property  
  14.             public int NumberOfReadings  
  15.           {  
  16.               get 
  17.               {  
  18.                   return numReadings;  
  19.                }  
  20.           }  
  21.           #endregion//NumberOfReadings Property  
  22.           #region Constructor  
  23.           public StatisticsDisplay(ISubject weatherData)  
  24.           {  
  25.               this.weatherData = weatherData;  
  26.               weatherData.RegisterObserver(this);  
  27.           }  
  28.           #endregion///Constructor  
  29.          #region IObserver Members  
  30.       //獲取更新的溫度數(shù)據(jù)  
  31.           public void Update(float temperature, float humidity, float pressure)  
  32.           {  
  33.               temperatureSum += temperature;  
  34.               numReadings++;  
  35.               if (temperature > maxTemp)   
  36.               {  
  37.                   maxTemp = temperature;  
  38.               }  
  39.               if (temperature < minTemp)   
  40.               {  
  41.                   minTemp = temperature;  
  42.               }  
  43.               Display();    
  44.           }  
  45.           #endregion   
  46.          #region IDisplayElement Members   
  47.            public void Display()  
  48.           {  
  49.               Console.WriteLine("Avg/Max/Min temperature = " +(temperatureSum / numReadings)+ "F/" + maxTemp + "F/" + minTemp + "F");  
  50.           }  
  51.           #endregion   
  52.  } 

#p#

2.6主類實(shí)現(xiàn)Program.cs:

  1. 主類實(shí)現(xiàn)  
  2.  public class program  
  3.      {//實(shí)現(xiàn)天氣監(jiān)測系統(tǒng)的主類  
  4.          public static void Main(String[] args)  
  5.          {  
  6.              WeatherData weatherData = new WeatherData();  
  7.              ForcastDisplay forecastDisplay = new ForcastDisplay(weatherData);  
  8.              StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);  
  9.              CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);  
  10.              weatherData.SetMeasurements(84, 66, 31.6f);  
  11.              weatherData.SetMeasurements(88, 72, 30.0f);  
  12.              weatherData.SetMeasurements(86, 85, 30.0f);  
  13.          }  
  14.      } 

2.7運(yùn)行后結(jié)果如下:

  1. Forecast: Improving weather on the way!  
  2.  
  3. Avg/Max/Min temperature = 84F/84F/84F  
  4.  
  5. Current conditions: 84F degrees and 66% humidity and 31.6f pressure  
  6.  
  7. Forecast: Watch out for cooler, rainy weather  
  8.  
  9. Avg/Max/Min temperature = 86F/88F/84F  
  10.  
  11. Current conditions: 88F degrees and 72% humidity and 30f pressure  
  12.  
  13. Forecast: More of the same  
  14.  
  15. Avg/Max/Min temperature = 86F/88F/84F  
  16.  
  17. Current conditions: 86F degrees and 85% humidity and 30f pressure 

五、觀察者模式總結(jié)

1.觀察者模式有以下的優(yōu)點(diǎn):

1.1觀察者模式在被觀察者和觀察者之間建立一個(gè)抽象的耦合。被觀察者角色所知道的只是一個(gè)具體觀察者列表,每一個(gè)具體觀察者都符合一個(gè)抽象觀察者的接口。被觀察者并不認(rèn)識(shí)任何一個(gè)具體觀察者,它只知道它們都有一個(gè)共同的接口。

由于被觀察者和觀察者沒有緊密地耦合在一起,因此它們可以屬于不同的抽象化層次。如果被觀察者和觀察者都被扔到一起,那么這個(gè)對象必然跨越抽象化和具體化層次。

1.2觀察者模式支持廣播通訊,被觀察者會(huì)向所有的登記過的觀察者發(fā)出通知。

1.3通過Observer模式,把一對多對象之間的通知依賴關(guān)系的變得更為松散,大大地提高了程序的可維護(hù)性和可擴(kuò)展性,也很好的符合了開放-封閉原則。

2.觀察者模式有下面的缺點(diǎn):

2.1如果一個(gè)被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。

2.2如果在被觀察者之間有循環(huán)依賴的話,被觀察者會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,導(dǎo)致系統(tǒng)崩潰。在使用觀察者模式時(shí)要特別注意這一點(diǎn)。

2.3如果對觀察者的通知是通過另外的線程進(jìn)行異步投遞的話,系統(tǒng)必須保證投遞是以自恰的方式進(jìn)行的。

2.4雖然觀察者模式可以隨時(shí)使觀察者知道所觀察的對象發(fā)生了變化,但是觀察者模式?jīng)]有相應(yīng)的機(jī)制使觀察者知道所觀察的對象是怎么發(fā)生變化的。

3.觀察者模式的適用性:

3.1當(dāng)一個(gè)抽象模型有兩個(gè)方面, 其中一個(gè)方面依賴于另一方面。將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立地改變和復(fù)用。

3.2當(dāng)一個(gè)對象的改變需要同時(shí)改變其它對象, 而不知道具體有多少對象有待改變。

3.3當(dāng)一個(gè)對象必須通知其它對象,而它又不能假定其它對象是誰。換言之, 你不希望這些對象是緊密耦合的?! ?/p>

源碼下載:天氣監(jiān)測系統(tǒng)的源碼 Weather

原文鏈接:http://www.cnblogs.com/YZDONET/archive/2012/08/15/2639702.html

責(zé)任編輯:林師授 來源: 博客園
相關(guān)推薦

2020-10-26 08:45:39

觀察者模式

2021-07-08 11:28:43

觀察者模式設(shè)計(jì)

2013-11-26 17:09:57

Android設(shè)計(jì)模式

2021-09-06 10:04:47

觀察者模式應(yīng)用

2022-01-29 22:12:35

前端模式觀察者

2011-04-29 09:22:22

2021-03-29 07:14:28

Spring觀察者模式

2015-11-25 11:10:45

Javascript設(shè)計(jì)觀察

2024-02-18 12:36:09

2024-12-03 09:34:35

觀察者模 式編程Javav

2024-06-04 13:11:52

Python行為設(shè)計(jì)模式開發(fā)

2009-03-30 09:39:04

觀察者思想換位設(shè)計(jì)模式

2021-06-03 12:26:28

觀察者模式面試阿里P6

2021-01-25 05:38:04

設(shè)計(jì)原理VueSubject

2021-09-29 19:45:24

觀察者模式Observable

2022-07-13 08:36:57

MQ架構(gòu)設(shè)計(jì)模式

2022-05-09 10:50:13

觀察者模式設(shè)計(jì)模式

2021-04-14 14:40:37

forSpringJava

2021-06-07 20:03:04

監(jiān)聽器模式觀察者

2022-11-15 07:35:50

Spring事件觀察者模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)