2012-08-17 55 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