每日一得

          不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發
          最近關心的內容:SSH,seam,flex,敏捷,TDD
          本站的官方站點是:顛覆軟件

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks
          key words: 觀察者模式 Observer模式

          definition:
          defines a one-to-many dependency between objects so that when one object changes state,all of its dependents are notified and updated automatically.

          物理模型:
          觀察者注冊
          observerpattern_02.gif

          觀察者通知:
          observerpattern_03.gif
          觀察者撤銷注冊
          observerpattern_04.gif

          business: weather station
          天氣預報,在預報的數據更新后自動通知到各類不同顯示類型的終端,前提是這些終端向預報中心注冊了預定服務(register the service),這一點類似于訂閱報紙,你'訂閱'了以后就可以呆在家等郵遞員給你送過來.
          看一下類圖:weather.png


          implement:
          public?interface?Subject?{
          ????
          public?void?registerObserver(Observer?o);
          ????
          public?void?removeObserver(Observer?o);
          ????
          public?void?notifyObservers();
          }

          public?class?WeatherData?implements?Subject?{
          ????
          private?ArrayList?observers;
          ????
          private?float?temperature;
          ????
          private?float?humidity;
          ????
          private?float?pressure;
          ????
          ????
          public?WeatherData()?{
          ????????observers?
          =?new?ArrayList();
          ????}
          ????
          ????
          public?void?registerObserver(Observer?o)?{
          ????????observers.add(o);
          ????}
          ????
          ????
          public?void?removeObserver(Observer?o)?{
          ????????
          int?i?=?observers.indexOf(o);
          ????????
          if?(i?>=?0)?{
          ????????????observers.remove(i);
          ????????}
          ????}
          ????
          ????
          public?void?notifyObservers()?{
          ????????
          for?(int?i?=?0;?i?<?observers.size();?i++)?{
          ????????????Observer?observer?
          =?(Observer)observers.get(i);
          ????????????observer.update(temperature,?humidity,?pressure);
          ????????}
          ????}
          ????
          ????
          public?void?measurementsChanged()?{
          ????????notifyObservers();
          ????}
          ????
          ????
          public?void?setMeasurements(float?temperature,?float?humidity,?float?pressure)?{
          ????????
          this.temperature?=?temperature;
          ????????
          this.humidity?=?humidity;
          ????????
          this.pressure?=?pressure;
          ????????measurementsChanged();
          ????}
          ????
          ????
          //?other?WeatherData?methods?here
          ????
          ????
          public?float?getTemperature()?{
          ????????
          return?temperature;
          ????}
          ????
          ????
          public?float?getHumidity()?{
          ????????
          return?humidity;
          ????}
          ????
          ????
          public?float?getPressure()?{
          ????????
          return?pressure;
          ????}
          }

          public?interface?Observer?{
          ????
          public?void?update(float?temp,?float?humidity,?float?pressure);
          }


          public?interface?DisplayElement?{
          ????
          public?void?display();
          }

          public?class?CurrentConditionsDisplay?implements?Observer,?DisplayElement?{
          ????
          private?float?temperature;
          ????
          private?float?humidity;
          ????
          private?Subject?weatherData;
          ????
          ????
          public?CurrentConditionsDisplay(Subject?weatherData)?{
          ????????
          this.weatherData?=?weatherData;
          ????????weatherData.registerObserver(
          this);
          ????}
          ????
          ????
          public?void?update(float?temperature,?float?humidity,?float?pressure)?{
          ????????
          this.temperature?=?temperature;
          ????????
          this.humidity?=?humidity;
          ????????display();
          ????}
          ????
          ????
          public?void?display()?{
          ????????System.out.println(
          "Current?conditions:?"?+?temperature?
          ????????????
          +?"F?degrees?and?"?+?humidity?+?"%?humidity");
          ????}
          }

          public?class?WeatherStation?{

          ????
          public?static?void?main(String[]?args)?{
          ????????WeatherData?weatherData?
          =?new?WeatherData();
          ???
          ??? ??? //register to weatherData(subscribe to weatherData)
          ????????CurrentConditionsDisplay?currentDisplay?
          =new?CurrentConditionsDisplay(weatherData);
          ????????StatisticsDisplay?statisticsDisplay?
          =?new?StatisticsDisplay(weatherData);
          ????????ForecastDisplay?forecastDisplay?
          =?new?ForecastDisplay(weatherData);

          ????????weatherData.setMeasurements(
          80,?65,?30.4f);
          ????????weatherData.setMeasurements(
          82,?70,?29.2f);
          ????????weatherData.setMeasurements(
          78,?90,?29.2f);
          ????}
          }


          public?class?WeatherStationHeatIndex?{

          ????
          public?static?void?main(String[]?args)?{
          ????????WeatherData?weatherData?
          =?new?WeatherData();
          ????????CurrentConditionsDisplay?currentDisplay?
          =?new?CurrentConditionsDisplay(weatherData);
          ????????StatisticsDisplay?statisticsDisplay?
          =?new?StatisticsDisplay(weatherData);
          ????????ForecastDisplay?forecastDisplay?
          =?new?ForecastDisplay(weatherData);
          ????????HeatIndexDisplay?heatIndexDisplay?
          =?new?HeatIndexDisplay(weatherData);

          ????????weatherData.setMeasurements(
          80,?65,?30.4f);
          ????????weatherData.setMeasurements(
          82,?70,?29.2f);
          ????????weatherData.setMeasurements(
          78,?90,?29.2f);
          ????}
          }


          other places to use Observe-Pattern in JDK:

          public?class?SwingObserverExample?{
          ????JFrame?frame;
          ????
          ????
          public?static?void?main(String[]?args)?{
          ????????SwingObserverExample?example?
          =?new?SwingObserverExample();
          ????????example.go();
          ????}
          ????
          ????
          public?void?go()?{
          ????????frame?
          =?new?JFrame();

          ????????JButton?button?
          =?new?JButton("Should?I?do?it?");
          ??? ??? //register to AngelListener and DevilListener

          ????????button.addActionListener(
          new?AngelListener());
          ????????button.addActionListener(
          new?DevilListener());
          ????????frame.getContentPane().add(BorderLayout.CENTER,?button);

          ????????
          //?Set?frame?properties?
          ????????frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          ????????frame.getContentPane().add(BorderLayout.CENTER,?button);
          ????????frame.setSize(
          300,300);
          ????????frame.setVisible(
          true);
          ????}
          ????
          ????
          class?AngelListener?implements?ActionListener?{
          ????????
          public?void?actionPerformed(ActionEvent?event)?{
          ????????????System.out.println(
          "Don't?do?it,?you?might?regret?it!");
          ????????}
          ????}

          ????
          class?DevilListener?implements?ActionListener?{
          ????????
          public?void?actionPerformed(ActionEvent?event)?{
          ????????????System.out.println(
          "Come?on,?do?it!");
          ????????}
          ????}
          }



          implement it with java built-in Observe-Pattern
          import?java.util.Observable;
          import?java.util.Observer;
          ????
          public?class?WeatherData?extends?Observable?{
          ????
          private?float?temperature;
          ????
          private?float?humidity;
          ????
          private?float?pressure;
          ????
          ????
          public?WeatherData()?{?}
          ????
          ????
          public?void?measurementsChanged()?{
          ????????setChanged();
          ????????notifyObservers();
          ????}
          ????
          ????
          public?void?setMeasurements(float?temperature,?float?humidity,?float?pressure)?{
          ????????
          this.temperature?=?temperature;
          ????????
          this.humidity?=?humidity;
          ????????
          this.pressure?=?pressure;
          ????????measurementsChanged();
          ????}
          ????
          ????
          public?float?getTemperature()?{
          ????????
          return?temperature;
          ????}
          ????
          ????
          public?float?getHumidity()?{
          ????????
          return?humidity;
          ????}
          ????
          ????
          public?float?getPressure()?{
          ????????
          return?pressure;
          ????}
          }






          增加一個看到的通俗版的解說:

          觀察者模式?Observer Pattern — 三國演義之超級間諜戰 — 美女貂蟬的故事

          說明:我也是初學者,希望大家能提出寶貴意見。另外轉載請注明作者左光和出處博客園,畢竟花費了很長時間才完成。

          情節:

          這一次講的故事情節很簡單,但是充滿了謀略和斗爭。大體意思就是三國初期,曹劉孫三家在徐州聯手消滅了呂布,但是自己也傷了元氣。而此時袁術得了傳國玉璽,在淮南稱帝,兵精將廣,圖謀不軌,對三家威脅都很大。于是曹劉孫三家在一起開了個會,決定派遣一名超級間諜打入到袁術身旁,監視他的一舉一動,這樣的話一旦袁術想干什么壞事,他們就可以立刻知道并做出相應的調整,知己知彼百戰百勝嘛。

          計是好計,問題是派誰去當這個超級間諜呢?正當大家愁眉苦臉的時候,美女貂蟬自告奮勇,想當年董卓那么厲害都讓 我滅了,何況一個小小的袁術呢?大家一聽,說的有理,于是就把貂蟬獻給了袁術當了妃子。另外三家還各派出一名小奸細常住在淮南城內,他們的任務是當聯絡 員,貂蟬有什么情報總不能自己曹劉孫三家挨個跑著送吧?直接丟給各國聯絡員,然后讓他們通知各自的主公就 OK 了!而三家只要一接到各自奸細的通知,就會立即做出反應。

          還有一個小插曲,袁術雖然收下了貂蟬,但是對她看管很嚴,大大方方地把情報送出去不太可能,逼不得以,貂蟬自己設計了一套密碼來傳遞情報,雖然加密 方法沒有公開,但是她想總有人可以破解了吧?沒錯,對諸葛亮來說就是小菜一碟,從此袁術穿什么內褲曹劉孫三家都知道得清清楚楚。

          分析:

          下面我們用 觀察者模式? 來分析一下上面這個故事

          1、美女貂蟬:貂蟬在觀察者模式中叫做被觀察者(Subject),主要任務是獨立的管理后臺數據和業務邏輯,同時盡可能不受前臺客戶端界面變化的影響。當然,還要負責登記或者注銷各個觀察者。

          在這個故事里,貂蟬僅僅維護了一個數據 ,就是情報 —? 私有變量 info ;另外還擁有一個業務邏輯,是用來加密 info 的方法 Reverse(string str) 。每次得到新的情報,她就會先加密,然后立刻找到在自己這登記過的聯絡員,讓這些聯絡員通知自己的主公應變。

          情報一旦發送出去, 貂蟬的任務就算完成了,具體曹劉孫三家怎么應對,是打是降還是另有其他方法,那是三家自己的事情,和她貂蟬就沒什么關系了。

          2、曹劉孫三家:曹劉孫三家在觀察者模式里叫做觀察者,主要任務就是從界面上用“各種方式”即時的反映出 被觀察者,所謂“各種方式”就是說用字符、圖形、聲音都可以表示同樣數據,外在表現不同而已,本質都是一些數據。所謂“即時”,就是說只要 被觀察者 發生變化, 觀察者 也會立刻跟著變化,用行話應該叫做刷新 Update吧。

          在這個故事里,我們可以看到運行結果中,每次貂蟬有什么新的情報,三家都會在屏幕上顯示出來,雖然很簡單,但 他們確實是用各自不同的方式表示了同樣的數據








          posted on 2006-08-07 20:07 Alex 閱讀(448) 評論(0)  編輯  收藏 所屬分類: design
          主站蜘蛛池模板: 寻乌县| 五家渠市| 昌吉市| 天峨县| 巴青县| 会理县| 麻江县| 辽中县| 绵阳市| 台中市| 新沂市| 德阳市| 贡觉县| 遂川县| 林周县| 黑河市| 鹿邑县| 新津县| 那坡县| 光山县| 江都市| 阳谷县| 南通市| 保定市| 泾源县| 罗城| 炉霍县| 吴川市| 和林格尔县| 弥勒县| 达州市| 繁昌县| 岑巩县| 南昌县| 泽普县| 鞍山市| 莲花县| 随州市| 蓬溪县| 林周县| 伊宁县|