使用觀察者(Observer)實現對象監聽

來源:互聯網
上載者:User

使用觀察者(Observer)實現對象監聽

Bromon原創 請尊重著作權

       有非常多的時候,我們希望自己的程式能夠監視資料的變化,然後做出響應,這種情況非常多,比如探測資料庫中資料的變化、檢測使用者狀態的變化等等。通常我們都缺乏一種雙工通訊的機制,只能選擇讓程式做論詢,隔一段時間檢測一次資料變化,記錄下來與上一次檢測結果做對比,從而判斷資料是否發生了變化。毫無疑問這樣的方式很笨拙,不僅寫起來痛苦,跑起來也耗資源,是典型的用80%的時間解決20%的問題。

       觀察者(Observer)是一種模式,也是Java中的一個API,它讓一個值對象(Value Object)具備自省的功能,當他發現自己的狀態改變了,就向相關的對象發送訊息,這樣的監聽方式當然比輪詢好。我感冒了自己會去醫院,用不著醫生每個月來問一次。禽獸·宇楓曾經給了我一段麻將遊戲的伺服器端代碼,本來是讓我研究一下麻將的演算法,但是卻被其中Observer的使用所吸引,這樣寫出來的伺服器執行效率很高。我曾經用線程池+反射+觀察者寫了一個立即訊息的伺服器,既有socket的方便也具備udp的高效,可惜後來因為大幅修改設計代碼作廢了,不過觀察者還是值得研究。

       Java的Observer API是對觀察者模式的一個實現。假設我們有一個對象容器,其中存放使用者訊息,我希望這個容器自省,當有新的訊息進來就自動觸發觀察者作出響應。首先定義訊息對象,是個很簡單的值對象:

package com.gwnet.smsMessenger.mm.bromon;

public class Message

{

private int id;

private String sender;

private String receiver;

private String content;

private String time;

//請自己實現set/get方法,比如:

public int getId()

{

         return id;

}

public void setId(int id)

{

this.id=id;

}

}

然後寫一個存放Message的容器,容器使用ArrayList來存放對象是個很好的選擇,也很簡單:

/*

* Created on 2004-8-11

*/

package com.gwnet.smsMessenger.mm.bromon;

import java.util.*;

/**

* @author Bromon

*/

public class MessageList extends Observable

{

    private List m=new ArrayList();

    private static MessageList ml=null;

    

    public MessageList()

    {

    }

    

    public static MessageList getInstance()

    {

        if(ml==null)

       {

           ml=new MessageList();

       }

        return ml;

    }

    

    public void add(Message msg)

    {

        m.add(msg);

        super.setChanged();

        super.notifyObservers(m);

    }

    

    public void del(Message msg)

    {

        m.remove(msg);

    }

}

這個類繼承了Observable類,並且對其中的add方法做了手腳,很明顯,add方法的作用是向ArrayList容器中放入一個對象,這正是我們想監聽的操作,所以有了:

uper.setChanged();

super.notifyObservers(m);

這意思是一旦調用add方法,這個類自己就會向所有註冊過的觀察者發送訊息,訊息內容是什麼呢?內容就是m,是存放訊息的容器,觀察者可以收到這個改變了狀態的容器,然後對它進行操作,從而實現了對容器的監聽,當然,我們只實現了對add方法的監聽,你也可以試試其他的。

需要特別注意的是這是一個不完整的單例類,寫成單例是為了要保證整個jvm中只有這一個存放訊息的容器,而不寫成完整的單例,原因是將來可能要提供另外的執行個體化方法。所以理解起來可能稍微難一點,大家可以參考一下設計模式中的單例模式。

下面就是編寫觀察者並且註冊它:

/*

* Created on 2004-8-11

*/

package com.gwnet.smsMessenger.bromon;

import java.util.*;

/**

* @author Bromon

*/

public class MessageObserver implements Observer

{

    /* (non-Javadoc)

     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)

     */

    public void update(Observable arg0, Object arg1)

    {

       List l=(List)arg1;

        Message m=(Message)l.get(l.size()-1);

        String receiver=m.getReceiver();

        System.out.println("給"+m.getReceiver()+”的新訊息:”+m.getContent());

    }

}

這個類繼承Oberver介面,update(Observable,Object)是必須提供的方法,在這個方法中我們接收被觀察類傳過來的資料(含有訊息的容器),然後取出其中最後一個,讀取它的內容。

Java裡的觀察者使用起來是非常簡單的。我們的例子好處是所有的操作都在記憶體中進行,而且不需要輪詢,效率非常高,缺點是一旦當機記憶體中的資料就丟失了,所以如果有一套比較完善的對象緩衝機制,就可以應付複雜的應用,寫出高效簡潔的多線程伺服器。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.