<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    iNeo

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      30 Posts :: 8 Stories :: 2 Comments :: 0 Trackbacks
       觀察家模式是一個事件通知模式,被觀察者發(fā)生某個事件,或者狀態(tài)發(fā)生某個變化,就通知觀察者,這樣觀察者就能采取適當(dāng)?shù)男袆印O旅嫖乙砸粋€簡單的例子來說明一下這個模式的應(yīng)用。

    我們都知道,蜜蜂是勤勞的精靈,它總是四處采蜜。只要花朵的花瓣一張開,她就飛上去采蜜。我們輕易就能想到,在這里,蜜蜂應(yīng)該是一個觀察者,而花朵是一個被觀察者。只要花朵發(fā)生花瓣張開事件,就通知了觀察者蜜蜂,蜜蜂就可以去采蜜了。

    現(xiàn)在我們就來用java程序模擬蜜蜂采蜜。

    JavaAPI為我們設(shè)計好了這個模式,我們的被觀察者需要繼承Observable類,而觀察者需要實現(xiàn)Observer接口。

    現(xiàn)在我們來看看實際的代碼:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class Flower extends Observable

    {

          public void open()          -----------------------------------------------1

          {

                   System.out.println("The flower is opening!");   -----------2

                   this.setChanged();        ----------------------------------------3

                   this.notifyObservers();   ---------------------------------------4

          }

          public void registObserver(Observer observer)   -------------------5

          {

                   this.addObserver(observer);            --------------------------6

          }

          public static void main(String[] args)

          {

          }

    }

    標(biāo)號1行定義了一個方法,在這個方法里,主要要做三件事:第一被觀察者的動作,見標(biāo)號2行的代碼;第二設(shè)置被觀察者的狀態(tài)變化,如標(biāo)號3行的代碼;第三通知觀察者,如標(biāo)號4行的代碼。

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class Bee implements Observer

    {

          public void update(Observable arg0, Object arg1)

          {

                   // TODO Auto-generated method stub

                   System.out.println("It is bee's meat time!");

          }

          public static void main(String[] args)

          {

          }

    }

    觀察者的實現(xiàn)比較簡單,主要就是要實現(xiàn)update方法,在這個方法里實現(xiàn)觀察者在觀察到被觀察者動作后所要做的動作。

    下面是測試代碼:

    Bee bee = new Bee();

                   Flower flower = new Flower();

                   flower.registObserver(bee);

                   flower.open();

    測試結(jié)果如下:

    The flower is opening!

    It is bee's meat time!

    現(xiàn)在我們已經(jīng)基本熟悉了觀察家模式的用法,可以用它來設(shè)計我們一些日常所見的現(xiàn)象。如我們常說的一句成語是“螳螂捕蟬,黃雀在后”就可以利用我們的觀察家模式來進(jìn)行設(shè)計。螳螂在四處搜尋著蟬,如果蟬趴在樹枝上一動不動,那么螳螂是很難發(fā)現(xiàn)蟬。但如果蟬一有動作,就會被螳螂發(fā)現(xiàn);螳螂一旦發(fā)現(xiàn)蟬,就會對蟬發(fā)起攻擊;但螳螂萬萬沒有想到,黃雀也在后面搜尋著螳螂,一旦螳螂有所動作,黃雀也會對螳螂發(fā)動攻擊。

    很明顯,蟬是一個被觀察者,而黃雀是一個觀察者,螳螂則對蟬來說是一個觀察者,對黃雀來說是一個被觀察者,所以螳螂既是觀察者又是被觀察者。

    代碼如下:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class Cicada extends Observable

    {

      public void move()

      {

          System.out.println("The cicada is moving....");

          this.setChanged();

          this.notifyObservers();

      }

      public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

      public static void main(String[] args)

      {

      }

    }

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class DevilHorse extends Observable implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          // TODO Auto-generated method stub

          System.out.println("It is time for Devil horse to attack....");

          this.setChanged();

          this.notifyObservers();

      }

      public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

      public static void main(String[] args)

      {

      }

    }

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class YellowBird implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          // TODO Auto-generated method stub

          System.out.println("It is time for a yellow bird to attrack....");

      }

      public static void main(String[] args)

      {

          

      }

    }

    在上面的代碼中,類DevilHorse既是觀察者,又是被觀察者,所以它既繼承了Observable類,又實現(xiàn)了Observer接口。

    下面是測試代碼:

    Cicada cicada = new Cicada();

          DevilHorse devilHorse = new DevilHorse();

          YellowBird yellowBird = new YellowBird();

          cicada.registObserver(devilHorse);

          devilHorse.registObserver(yellowBird);

          cicada.move();

    運行結(jié)果:

    The cicada is moving....

    It is time for Devil horse to attack....

      It is time for a yellow bird to attrack....

    到了上面為止,我們已經(jīng)把觀察家模式全面的剖析了一遍。現(xiàn)在來對該模式作一些深入的研究。

    我們還是以蜜蜂采花為例,現(xiàn)在我們加入鳥兒吃蜂這一個案例。很明顯,我們的Flower類不用變,而Bee類則既是觀察者又是被觀察者,需要做改動為如下代碼:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class Bee extends Observable implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          // TODO Auto-generated method stub

          System.out.println("It is bee's meat time!");

          this.setChanged();

          this.notifyObservers();

      }

      public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

      public static void main(String[] args)

      {

      }

    }

    Bird類為:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public class Bird implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          // TODO Auto-generated method stub

          System.out.println("It is a bird's meat time....");

      }

      public static void main(String[] args)

      {

      }

    }

    測試代碼:

    Bee bee = new Bee();

          Bird bird = new Bird();

          Flower flower = new Flower();

          flower.registObserver(bee);

          bee.registObserver(bird);

          flower.open();

    測試結(jié)果:

    The flower is opening!

    It is bee's meat time!

      It is a bird's meat time....

    我們看看上面的被觀察者類,方法:

    public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

    每次都被原封不動的照抄下來;而在被觀察者的動作方法里頭,總有

    this.setChanged();

          this.notifyObservers();

    這兩句是必須照抄的。

    每一個被觀察者都必須這樣,很明顯,這是冗余代碼,我們需要想辦法解決。對于這樣的冗余代碼,我們可以輕松的想到用模板方法模式來解決。

    還有,我們來看測試代碼,我們對類的初始化都有很明顯的局限性。如:

    Bee bee = new Bee();

          Bird bird = new Bird();

          Flower flower = new Flower();

    flower.registObserver(bee);

    我們來看flowerbee的依賴關(guān)系,我們都知道依賴顛倒原則說的是要依賴抽象而不要依賴具體實現(xiàn),而flowerbee的依賴明顯是依賴具體實現(xiàn)bee,不滿足依賴顛倒原則。這帶來的缺點也是顯而易見的:如果有一個蝴蝶類也在觀察著Flower類,那么在運行期才能知道Flower類的觀察者,該怎么辦?

    以上的兩個缺點需要我們對觀察家模式作進(jìn)一步的包裝。

    我們首先對被觀察者作包裝,代碼如下:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public abstract class BaseObservable extends Observable

    {

      protected void baseDo()

      {

          observableDo();

          this.setChanged();

          this.notifyObservers();

      }

      public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

      public abstract void observableDo();

    }

    BaseObservable類是一個模板方法模式的一個直接應(yīng)用。我們的被觀察者只要繼承了這個類,就只需實現(xiàn)observableDo即可,在該方法里只寫被觀察者的動作,而無須關(guān)注其他。

    然后是對既是觀察者又是被觀察者的類進(jìn)行包裝:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public abstract class BaseObservableObserver extends Observable implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          // TODO Auto-generated method stub

          observableObserverDo(arg0,arg1);

          this.setChanged();

          this.notifyObservers();

      }

      public void registObserver(Observer observer)

      {

          this.addObserver(observer);

      }

      public abstract void observableObserverDo(Observable arg0, Object arg1);

      public static void main(String[] args)

      {

      }

    }

    同樣,我們的觀察和被觀察者只要繼承了BaseObservableObserver類,就只要實現(xiàn)observableObserverDo方法即可,在這個方法里頭實現(xiàn)它的動作。

    最后是對觀察者的包裝:

    package observer;

    import java.util.Observable;

    import java.util.Observer;

    public abstract class BaseObserver implements Observer

    {

      public void update(Observable arg0, Object arg1)

      {

          ObserverDo(arg0,arg1);

      }

      public abstract void ObserverDo(Observable arg0, Object arg1);

      public static void main(String[] args)

      {

      }

    }

    同樣,觀察者只要繼承了BaseObserver類,就只要在ObserverDo方法里實現(xiàn)觀察家的動作就好了。

    下面我們來重新設(shè)計FlowerBeeBird類:

    package observer;

    public class Flower extends BaseObservable

    {

      public void observableDo()

      {

          System.out.println("The flower is opening...");

      }

    }

    package observer;

    import java.util.Observable;

    public class Bee extends BaseObservableObserver

    {

      public void observableObserverDo(Observable arg0, Object arg1)

      {

          System.out.println("It is a bee's meal time...");

      }

    }

    package observer;

    import java.util.Observable;

    public class Bird extends BaseObserver

    {

      public void ObserverDo(Observable arg0, Object arg1)

      {

          System.out.println("aha,it's a bird's meal time...");

      }

    }

    現(xiàn)在我們可以看到這三個類簡潔了很多,只有和業(yè)務(wù)相關(guān)的動作方法,來看我們的測試類:

    BaseObservable flower = new Flower();

          BaseObservableObserver bee = new Bee();

          BaseObserver bird = new Bird();

          flower.registObserver(bee);

          bee.registObserver(bird);

          flower.baseDo();

    測試結(jié)果:

    The flower is opening...

    It is a bee's meal time...

      aha,it's a bird's meal time...

    我們可以看到,flowerbee的依賴關(guān)系也由具體類Bee變成了抽象類BaseObservableObserver。有利于我們的系統(tǒng)擴(kuò)展。

    如,我們增加了一個Butterfly類:

    package observer;

    import java.util.Observable;

    public class Butterfly extends BaseObservableObserver

    {

      public void observableObserverDo(Observable arg0, Object arg1)

      {

          System.out.println("The butterfly is coming for a meal...");

      }

    }

    我們的測試端就可以有這樣的代碼:

    BaseObservable flower = new Flower();

          BaseObservableObserver bee = new Bee();

          BaseObservableObserver butterfly = new Butterfly();

          BaseObserver bird = new Bird();

          ArrayList list = new ArrayList();

          list.add(bee);

          list.add(butterfly);

          for(int i=0;i<list.size();i++)

          {

               BaseObservableObserver boo = (BaseObservableObserver)list.get(i);

               flower.registObserver(boo);

               boo.registObserver(bird);

          }

          flower.baseDo();

    這樣使得觀察家模式更加靈活和易于擴(kuò)展。

    測試結(jié)果:

    The flower is opening...

    The butterfly is coming for a meal...

    aha,it's a bird's meal time...

    It is a bee's meal time...

      aha,it's a bird's meal time...



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=547850

    posted on 2005-12-09 16:26 只牽這只狗 閱讀(337) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 黄色一级免费网站| 亚洲色图.com| 亚洲精品高清在线| 亚洲av麻豆aⅴ无码电影 | 亚洲色偷精品一区二区三区| 亚洲精彩视频在线观看| 亚洲欧洲日产国产综合网| 亚洲av综合av一区| 久久精品国产亚洲AV无码娇色| 亚洲成人中文字幕| 亚洲网站免费观看| 亚洲乱码在线卡一卡二卡新区| 国产亚洲精品成人AA片| 亚洲AV无码一区二区大桥未久| 亚洲AⅤ男人的天堂在线观看| 国产偷国产偷亚洲清高APP| 粉色视频在线观看www免费| 免费一区二区三区在线视频| www在线观看免费视频| 天黑黑影院在线观看视频高清免费 | 久久精品国产亚洲Aⅴ香蕉| 亚洲夜夜欢A∨一区二区三区| 久久精品九九亚洲精品天堂| 久久精品亚洲综合| 亚洲电影唐人社一区二区| 亚洲av乱码一区二区三区香蕉 | 久久久久久a亚洲欧洲aⅴ| 久久亚洲AV成人无码软件| 亚洲一卡2卡4卡5卡6卡残暴在线| 亚洲va久久久久| 一级毛片a女人刺激视频免费| 日批视频网址免费观看| 最近免费视频中文字幕大全| 毛片免费观看的视频| 亚洲第一区精品日韩在线播放| 亚洲无线码在线一区观看| 亚洲美女视频网站| 综合偷自拍亚洲乱中文字幕 | 亚洲欧美日韩久久精品| 一级特黄a免费大片| 日韩在线永久免费播放|