隨筆-295  評論-26  文章-1  trackbacks-0
          java 觀察者模式
          2009-09-10 09:51

          觀察者模式可以參考郵件訂閱的例子

          郵件訂閱設計到2個主要角色,一個是訂閱者(觀察者),一個是發布者

          發布者可以擁有一個觀察者的集合,可以添加,刪除觀察者,當發布者發布一個新的消息時,要郵件通知觀察者集合中的每一個。

          所以,發布者實現的接口至少應具備三個方法,即注冊觀察者,注銷觀察者,通知觀察者。

          通知有兩種方式,一種是推(push),一種是拉(pull).

          推,即發布者通過調用觀察者提供的接口,來告之所有的變動(比如新增一個消息),主動推送給觀察者。

          拉,及觀察者可以按需提取所要接受的數據,而不是全盤接受,主要體現在程序自己主動調用觀察者的傳值接口,而區別于推由發布者來調用,此時,需要這個借口中的參數包含發布者對象,讓程序知道掃描變動來自于哪個發布者。

          JDK中內置了觀察者模式,位于java.util包中,一個接口Observer,一個類Observable,將這兩個類組合起來使用,既可以推,又可以拉。

          一個普通的類,如果繼承了Observable,就成了一個發布者,實現了Observer接口,就成了觀察者。

          JDK中的觀察者模式有一個弊端,就是發布者需要繼承一個類,而不是實現一個接口,如果需要成為發布者的類已經集成了一個類,就不能再繼承Observable了。這時候,就需要自己來設計一種觀察者模式了。

          JDK 中Swing包中,大量運用了觀察者模式,所有的組件都繼承了JComponent,這就是一個發布者,它里面包含一個監聽器的集合:EventListenerList,用戶可以自定義一個監聽器,然后添加到一個組件中的時候,該組件就會把這個監聽器注冊到 EventListenerList中,相當于添加了一個發布者,當用戶對組件做出反映時,所有的監聽器(發布者)都會收到信息并作出反應。

          網上商店中的商品在名稱、價格發生變化時,必須自動通知會員,Java的API為我們提供了
             Observer接口和Observable類來實現所謂觀察者模式。Observable(可觀察者)類允許在自身發生改變時,通知其它對象(實現接口Observer,觀察者)。


             下面是一個可觀察者(產品類):
          import java.util.*;
          public class product extends Observable{
             private String name;////產品名
             private float price;////價格

             public String getName(){ return name;}
             public void setName(String name){
             this.name=name;
             ////設置變化點
             setChanged();
             notifyObservers(name);////通知觀察者

             }   

             public float getPrice(){ return price;}
             public void setPrice(float price){
             this.price=price;
             ////設置變化點
             setChanged();
             notifyObservers(new Float(price));

             }

             ////以下可以是數據庫更新 插入命令.
             public void saveToDb(){
             System.out.println("saveToDb");
               }

          }

          下面是兩個觀察者:
          import java.util.*;
          public class NameObserver implements Observer{

             private String name=null;
             public void update(Observable obj,Object arg){
               if (arg instanceof String){
               name=(String)arg;
               ////產品名稱改變值在name中
               System.out.println("NameObserver :name changet to "+name);

               }

                  }
             }

          import java.util.*;
          public class PriceObserver implements Observer{
             private float price=0;
             public void update(Observable obj,Object arg){
               if (arg instanceof Float){

               price=((Float)arg).floatValue();
            
               System.out.println("PriceObserver :price changet to "+price);

               }


             }

          }
          下面是測試類:
          public class Test {

             public static void main(String args[]){
                Product product=new Product();
                NameObserver nameobs=new NameObserver();
                PriceObserver priceobs=new PriceObserver();

                ////加入觀察者
                product.addObserver(nameobs);
                product.addObserver(priceobs);

                product.setName("applet");
                product.setPrice(9.22f);

             }
          }
          運行結果:
          C:\java>java    Test
          NameObserver :name changet to applet



          大盤預測 國富論
          posted on 2009-10-22 10:16 華夢行 閱讀(516) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 扶余县| 高密市| 旌德县| 阳西县| 平江县| 深泽县| 日照市| 彭阳县| 抚州市| 民乐县| 湘潭县| 融水| 乐亭县| 巩义市| 清远市| 措美县| 西青区| 淮滨县| 安仁县| 恩平市| 保靖县| 北碚区| 大新县| 竹山县| 怀仁县| 昭平县| 乌拉特前旗| 甘孜县| 安义县| 福海县| 新建县| 金川县| 景谷| 全南县| 靖西县| 富宁县| 门头沟区| 平湖市| 邵武市| 旌德县| 信丰县|