2012-08-17 53 views
0

全部,一般Java類設計屬性與集合需要監聽更改

希望有一個簡單的問題。我正在考慮實現一個擁有多個集合和HashMaps的類的最佳方式,其中類需要知道它們何時被修改以外的類 - 即添加/刪除/更改的項目。每個集合/散列映射現在都需要在我的課堂中作爲公共獲取者公開。

所以我的基本類看起來如下...

public class MyClass { 

    protected final HashMap<String, String> _values = new HashMap<String, String>(); 
    protected final ArrayList<MyOtherClass> _other = new ArrayList<MyOtherClass>(); 
    protected final ArrayList<MyOtherClass2> _other2 = new ArrayList<MyOtherClass2>(); 

    // ... implementation 


    public HashMap<String, String> getValues() { 
     return _values; 
    } 

    public ArrayList<MyOtherClass> getMyOtherClassList() { 
     return _other; 
    } 

    public ArrayList<MyOtherClass2> getMyOtherClassList2() { 
     return _other2; 
    } 

    public String getContent() { 
     // build the content based on other/other2... 
     StringBuilder sb = new StringBuilder(); 
     // iterate through both collections to build content... 
     // ... 
     return sb.toString(); 
    } 
} 

public getMyOtherClass { 
    public String name; // has getter and setter 
    public String value; // has getter and setter 
} 

public getMyOtherClass2 { 
    public String name; // has getter and setter 
    public String value; // has getter and setter 
    public String somethingElse; // has getter and setter 
} 

我想基於內容的長度,即 -

_values.add("Length", getContent().length); 

所以添加一個鍵/值對_values根據添加到_other和_other2的內容,長度值是動態的。

這個問題暴露了_values和_other與公共getter是類外的任何東西都可以修改它們。課程將不知道項目是否已被修改。

我能想到的一些解決方案是使collection/hashmap只讀 - 但是這會引發一個運行時異常 - 如果是這種情況,我希望編譯器指出它們是隻讀的並且拋出一個例外,但我不知道這是否可能。

另一種方法是爲每個集合/地圖添加一個add/remove並相應地更新Length屬性 - 但是,如果MyOtherClass中的值發生更改,MyClass仍然不知道它。

或者編寫我自己的Hashmap/List/Collection來確定何時添加/刪除項目,並且可能在getMyOtherClass,getMyOtherClass2上具有屬性更改偵聽器。

任何漂亮的解決方案呢?

感謝,

Andez

回答

1

此改變map/list實現並插入一個回調到add/update/remove方法觸發父的更新功能。
同樣是不好的形式直接創建引用的實現 - 這是更好的(多態推理閱讀起來):

private Map<String,String> myMap = new HashMap<String,String>(); 
private List<String> myList = new List<String>(); 
+0

丹,好點。我手動複製和粘貼我的示例類,所以appologies。但是List <>也是一個接口;-) – Andez 2012-08-17 12:39:15

1

在這種情況下,你可以使用Observer設計模式的一些基本面有一個對象「觀看」地圖並註冊每個變化。

創建一個對象包含一個Map和另一個包含List的對象,因此,由於您有1個映射和2個列表,因此您將擁有3個這些「可觀察」對象。我們來命名類「ObservableMap」和「ObservableList」。你甚至可以創建一個抽象類「ObservableObject」並用前面提到的類擴展它。

這些對象不會重寫Map/List實現,它們只會通過包裝要跟蹤的方法來註冊狀態並派生調用以修改集合,從而充當包裝器。例如,我將發佈ObservableMap類的一些代碼(我正在使用<String,String>實例化地圖,但如果它適合您,也可以在這裏使用泛型)。

public Class ObservableMap extends ObservableObject{ 
    private Map<String,String> map = new LinkedHashMap<String,String>(); 
    private Watcher observer = new Watcher(); 

    //Example of one of the wrapper methods (the other ones are like this one) 
    public void putObject(String key, String value) { 
     watcher.notifyPut(); //You can name the method the way you like and even pass 
          //the new key/value pair to identify what has been added. 
     map.put(key,value); 
    } 
} 

在這裏,Watcher類是註冊這些canges的類。它可以是一個全新的對象(就像這種情況一樣),或者你可以創建一個接口並在你現有的類中實現它,以便能夠將它設置爲Observable對象上的一個觀察器。

+0

謝謝你會檢查這個 – Andez 2012-08-17 13:14:08

0

不是100%確定你在問什麼。如果您試圖追蹤屬性對兩個類的更改,您可能會希望,因爲其他人已經提到實現觀察者模式並在set方法中引發通知。另一種方法,我成功用於實現撤銷機制的方法是使用aspectJ或其他AOP(面向方面​​編程)工具來截取所設置的方法並以此方式執行所需的通知/更新。

或者定義一個接口,該接口只提供對getXXX操作的訪問並從模型中返回這些操作,這樣沒有什麼可以更改數據。

+0

嗨vickirk,我最好想暴露的getters,以便他們可以在課外修改,但暴露他們的類知道任何更改。要檢查觀察者模式。 – Andez 2012-08-17 13:04:20