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

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

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

    常用鏈接

    統計

    最新評論

    JavaBean PropertyChange 之設計模式Observer(轉)

    java語言里包含了許多對設計模式的直接支持,如command模式,agent模式,observer模式等。雖然java提供的對這些模式的支持很簡單,不能滿足比較復雜的應用。但在簡單的場景下,使用這些類往往能夠得到立桿見影的效果。所以,如果沒有什么特殊需求,還是最好利用java的這些類。

            Observer模式,又稱監聽模式,觀察者模式,是經典設計模式之一(one of GOF)。java語言中,對這種模式支持的類和接口主要有以下幾個,全部來自java.beans包:

    java.beans.PropertyChangeListener (interface)  

    java.beans.PropertyChangeSupport  (class)

    java.beans.PropertyChangeEvent (class)

    • java.beans.PropertyChangeListener

          這是一個接口,很顯然,所有實現這個接口的類就是listener啦(或者叫observer),它會對被監聽的對象的某些變化感興趣。這個接口就一個方法:

    java 代碼
    1. public void propertyChange(PropertyChangeEvent evt) {   
    2. // TODO Auto-generated method stub   
    3.  

    接口定義很簡單,作用也很明顯。接受一個event(被監聽者產生的PropertyChangeEvent),然后根據這個event做點反應。

    •   java.beans.PropertyChangeSupport 

             這個類用在被觀察者的類里,用來保存注冊的觀察者,并負責向他們提供被觀察者的變化信息。這個類的方法也不多,不過還是只介紹100%用到的,要不腦子就不夠使了,呵呵。

    java 代碼
    1. public PropertyChangeSupport(Object sourceBean)  

          這是構造函數,參數就是被監聽者。PropertyChangeListener一般作為被監聽者的一個屬性。一般如下使用:

    java 代碼
    1. private PropertyChangeSupport listeners new PropertyChangeSupport(this);  

          注意,這個listeners可不是只代表一個監聽者,他可能是一群監聽者。那么如何這些listeners是誰呢?這回用到下面的方法了。

    java 代碼
    1. public void addPropertyChangeListener(PropertyChangeListener listener)  

            這個類太容易了,把監聽者加進來。就像開十七大一樣,記者想要采訪,就得先登記一下。顯然這個方法可以多次調用(add嘛)。有加就有減:

    java 代碼
    1. public void removePropertyChangeListener(PropertyChangeListener listener)  

    如果這個監聽者對被監聽者的任何變化多不感興趣了,就被被監聽者趕了出去。

    好了,記者都到齊了,被監聽者有變化了就該通知人家了,使用如下方法的一個:

    java 代碼
    1. public void firePropertyChange(PropertyChangeEvent evt)   
    2.   
    3. public void firePropertyChange(String propertyName,   
    4.                                boolean oldValue,   
    5.                                boolean newValue)   
    6.   
    7. public void firePropertyChange(String propertyName,   
    8.                                int oldValue,   
    9.                                int newValue)   
    10.   
    11. public void firePropertyChange(String propertyName,   
    12.                                Object oldValue,   
    13.                                Object newValue)  

    實際上,后三個方法的參數都會封裝成PropertyChangeEvent,然后調用第一個方法。不過在實際中,我們還是喜歡直接調用后三個中的一個,封裝的事我們就不管了。后三個方法的參數都是三個,其中的oldValue和 newValue就是改變前后的值,第一個就是給改變一個名字,好讓監聽者們根據這個名子來做響應。就像開會,政府的所有信息都會被記者聽到,但是有的記者只對臺灣問題感興趣,而有的記者對中日問題感興趣。

    PropertyChangeSupport方法的介紹就這么多吧。注意,PropertyChangeSupport既然被用到了被觀察者的類(一般是一個model)里,那么他的這些方法就只在被觀察這里調用。

    • java.beans.PropertyChangeEvent

           這個類我也懶得介紹,看看他的主要方法就明白怎么回事了

    java 代碼
    1. public String getPropertyName()   
    2. public Object getNewValue()   
    3. public Object getOldValue()  

    就者三個類,再有就是具體問題具體分析了。來個例子吧,首先是被觀察者:

    java 代碼
    1. public class Domain{   
    2.     protected String id;   
    3.     protected String name;   
    4.     protected String desName;   
    5.   
    6.     protected PropertyChangeSupport listeners new PropertyChangeSupport(this);   
    7.   
    8.     public String getId() {   
    9.         return id;   
    10.     }   
    11.   
    12.     public void setId(String id) {   
    13.         this.id id;   
    14.         firePropertyChange("Domain.id"nullid);   
    15.     }   
    16.   
    17.     public String getDesName() {   
    18.         return desName;   
    19.     }   
    20.   
    21.     public void setDesName(String desName) {   
    22.         this.desName desName;   
    23.         firePropertyChange("Domain.desName"nulldesName);   
    24.     }   
    25.   
    26.     public String getName() {   
    27.         return name;   
    28.     }   
    29.   
    30.     public void setName(String name) {   
    31.         this.name name;   
    32.         firePropertyChange("Domain.name"nullname);   
    33.     }   
    34.   
    35.     public void addPropertyChangeListener(PropertyChangeListener listener) {   
    36.         listeners.addPropertyChangeListener(listener);   
    37.     }   
    38.   
    39.     public void firePropertyChange(String propName, Object oldValue, Object newValue) {   
    40.         listeners.firePropertyChange(propName, oldValue, newValue);   
    41.     }   
    42.   
    43.     public void removePropertyChangeListener(PropertyChangeListener listener) {   
    44.         listeners.removePropertyChangeListener(listener);   
    45.     }   
    46.  

    有人對Domain的三個屬性感興趣。下面就是這些人中的一個:

    java 代碼
    1. public class SimpleObserver implements PropertyChangeListener {   
    2.        
    3.     ....   
    4.        
    5.     @Override  
    6.     public void propertyChange(PropertyChangeEvent evt) {   
    7.         if(evt.getPropertyName().equals("Domain.name")){   
    8.             //do some work   
    9.         }   
    10.     }   
    11.        
    12.  

    下面是個簡單的測試類:

    java 代碼
    1. public class SimpleTest{   
    2.     public static void main(String[] args) {   
    3.         SimpleObserver observer new SimpleObserver();   
    4.         Domain domain new Domain();   
    5.         domain.addPropertyChangeListener(observer);   
    6.         domain.setName("yangsq");   
    7.         ......   
    8.     }   
    9.  
    關于JavaBean的PropertyChangeListener

    JavaBean的屬性與一般Java程序中所指的屬性,或者說與所有面向對象的程序設計語言中對象的屬性是一個概念,在程序中的具體體現就是類中的變量。在JavaBean的設計中,按照屬性的不同作用又細分為四類:單值屬性;索引屬性;關聯屬性;限制屬性。

      本文主要介紹如何使用PropertyChangeSupport類來支持關聯屬性事件的觸發。

      1.關聯屬性

      關聯屬性,也稱之為綁定屬性。綁定屬性會在屬性值發生變化時,通知所有相關的監聽器。為了實現一個綁定屬性,必須實現兩個機制。

      1) 無論何時,只要屬性的值發生變化,該bean必須發送一個PropertyChange事件給所有已注冊的監聽器。該變化可能發生在調用set方法時,或者程序的用戶做出某種動作時。

      2) 為了使感興趣的監聽器能夠進行注冊,bean必須實現以下兩個方法:

    void addPropertyChangeListener(PropertyChangeListener listener);
    void removePropertyChangeListener(PropertyChangeListener listener);

      2.使用PropertyChangeSupport管理監聽器

      可以通過java.bean包下的PropertyChangeSupport類來管理監聽器。要使用這個類,bean必須有一個此類的數據域。

    private PropertyChangeSupport changes = new PropertyChangeSupport(this);

      這樣就可以將添加和移除監聽器的任務交給這個對象。

    public void addPropertyChangeListener(PropertyChangeListener listener) {
    changes.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener listener) {
    changes.removePropertyChangeListener(listener);
    }

    當bean的屬性發生變化時,使用PropertyChangeSupport對象的firePropertyChange方法,它會將一個事件發送給所有已經注冊的監聽器。該方法有三個參數:屬性的名字、舊的值以及新的值。屬性的值必須是對象,如果是簡單數據類型,則必須進行包裝。

    changes.firePropertyChange("ourString", oldString, newString);

      所有注冊的監聽器實現PropertyChangeListener接口,該接口中只有一個方法。

    public void propertyChange(PropertyChangeEvent e);

      當bean的屬性值發生變化時,該方法中的代碼就會被觸發。可以通過

      e.getOldValue();

      e.getNewValue();

      來得到changes.firePropertyChange("ourString", oldString, newString);中的oldString和newString。

      3.為什么要使用PropertyChangeSupport

      使用這個類管理監聽器的好處是,它是線程安全的。如果使用一個循環體來set Bean的屬性,則這個類可以保證所有監聽器執行觸發事件的有序。

      還有一個好處是,這個類支持fire帶索引的屬性改變事件(詳見java.bean.IndexedPropertyChangeEvent)。此時向注冊的監聽器發送一個PropertyChangeEvent的方法為:

    void fireIndexedPropertyChange(String PropertyName,int index,Object oldValue,Object newValue);

      4.示例

      MyBoundBean類(具體代碼見附件)是一個JavaBean,我們關注它的唯一一個屬性ourString的變化情況,它的初始值是Hello。并通過PropertyChange類來管理監聽器。注意在set方法中會調用firePropertyChange方法。

    MyBoundBean.java
    import java.beans.PropertyChangeListener;
    import java.beans.PropertyChangeSupport;
    public class MyBoundBean {
    String ourString = "Hello";
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);
    public void setString(String newString) {
    String oldString = ourString;
    ourString = newString;
    changes.firePropertyChange("ourString", oldString, newString);
    }
    public String getString() {
    return ourString;
    }
    public void addPropertyChangeListener(PropertyChangeListener listener) {
    changes.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener listener) {
    changes.removePropertyChangeListener(listener);
    }
    }

    Java:在Bean中使用PropertyChangeSupport支持PropertyChangeListeners

     

    MyBoundBean b = new MyBoundBean();

    public void actionPerformed(ActionEvent e) {
    jButton1.setText(textBox.getText());
    b.setString(textBox.getText());
    }

      目標bean的屬性一改變(注意,初始值是"Hello"),將會觸發propertyChange方法的執行。將文本框的內容設置為目標bean的ourString屬性的舊值,同時,將jButton2的test設置成目標bean的ourString屬性的新值。

    public void propertyChange(PropertyChangeEvent e) {
    if (e.getSource() == b) {
    textBox.setText(e.getOldValue().toString());
    jButton2.setText(e.getNewValue().toString());
    }
    }

    Java:在Bean中使用PropertyChangeSupport支持PropertyChangeListeners

      如果不實現PropertyChangeListener接口的話,可以使用匿名內部類來達到同樣的效果。(具體代碼見附件MyCallBound2.java)

    MyBoundBean b = new MyBoundBean();

    b.addPropertyChangeListener(new PropertyChangeListener() {
    public void propertyChange(PropertyChangeEvent e) {
    // 這樣一來,我們就可以用自己定義的名字實現事件
    ourString_propertyChange(e);
    }
    });

     

      這樣一來,我們就可以用自己定義的名字實現事件。

    void ourString_propertyChange(PropertyChangeEvent e) {
    if (e.getSource() == b) {
    textBox.setText(e.getOldValue().toString());
    jButton2.setText(e.getNewValue().toString());
    }
    }

    很顯然,可以觀察到SimpleObserver中propertyChange方法的執行。

    posted on 2011-02-13 18:26 九寶 閱讀(942) 評論(0)  編輯  收藏 所屬分類: Java Study(JavaThinking4)

    主站蜘蛛池模板: 精品免费久久久久久成人影院| 亚洲人成人一区二区三区| 色噜噜狠狠色综合免费视频| 久久精品国产亚洲Aⅴ蜜臀色欲| 国产情侣久久久久aⅴ免费| 亚洲国产精品日韩在线| 暖暖日本免费在线视频| 国产成人无码区免费网站| 亚洲午夜国产精品无卡| 亚洲精品无码久久毛片| www视频免费看| 一个人看的免费观看日本视频www| 亚洲永久永久永久永久永久精品| 在线jlzzjlzz免费播放| 国产免费无码AV片在线观看不卡| 波多野结衣亚洲一级| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 午夜时刻免费入口| 91成人免费福利网站在线| 亚洲中文字幕乱码AV波多JI| 在线亚洲97se亚洲综合在线| 100000免费啪啪18免进| 精品免费久久久久国产一区| 亚洲综合一区无码精品| 久久99国产亚洲精品观看| 免费观看午夜在线欧差毛片| 毛片免费全部播放无码| 精品一区二区三区高清免费观看| 亚洲AV无码一区二区三区人| 国产亚洲综合久久系列| 国产乱弄免费视频| 日韩欧毛片免费视频| 国产免费拔擦拔擦8X高清在线人| 免费的黄网站男人的天堂| 亚洲伊人精品综合在合线| 久久亚洲综合色一区二区三区 | 亚洲免费网站在线观看| 国产中文字幕在线免费观看| 男女超爽视频免费播放| 亚洲人成电影网站色www| 亚洲国产精品久久网午夜|