<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 九寶 閱讀(941) 評論(0)  編輯  收藏 所屬分類: Java Study(JavaThinking4)

    主站蜘蛛池模板: 日本一区二区三区免费高清在线| 91网站免费观看| 亚洲美女视频网址| 成年人在线免费看视频| 国产大片免费天天看| 亚洲福利电影一区二区?| 亚洲电影日韩精品 | 久久国产成人亚洲精品影院 | 男人的天堂亚洲一区二区三区| 四虎一区二区成人免费影院网址| 久久久亚洲欧洲日产国码二区| 国产免费啪嗒啪嗒视频看看| 国产va在线观看免费| 亚洲JIZZJIZZ妇女| 亚洲免费视频在线观看| 国产一级理论免费版| 57pao国产成视频免费播放| 五级黄18以上免费看| 亚洲六月丁香婷婷综合| 亚洲欧洲成人精品香蕉网| 日韩激情无码免费毛片| 30岁的女人韩剧免费观看| 一本岛v免费不卡一二三区| 亚洲AV无码一区二区三区牛牛| 亚洲爆乳无码一区二区三区| 国产美女精品久久久久久久免费| 日日麻批免费40分钟无码| 国产成人无码精品久久久免费 | 亚洲第一成年网站视频| 亚洲专区在线视频| 国产综合亚洲专区在线| 永久免费毛片手机版在线看| 最近2019免费中文字幕6| 国产美女视频免费观看的网站| 亚洲高清毛片一区二区| 亚洲乱码卡三乱码新区| 久久久久亚洲精品天堂| 亚洲精品白浆高清久久久久久 | 亚洲字幕在线观看| 亚洲精品国产成人99久久| 亚洲中文字幕无码日韩|