0

全部,

希望是一个简单的问题。我正在考虑实现一个包含许多集合和 HashMap 的类的最佳方法,在这些集合和 HashMap 中,类需要知道它们何时在类之外被修改- 即添加/删除/更改的项目。目前,每个集合/哈希图都需要在我的班级中公开为公共 getter。

所以我的基本课程如下所示......

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 添加一个键/值,即-

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

因此,长度值是动态的,基于添加到 _other 和 _other2 的内容。

这样做的问题是使用公共 getter 公开 _values 和 _other 是类之外的任何东西都可以修改它们。该类将不知道项目是否已被修改。

我能想到的几个解决方案是使集合/哈希图只读-但这会引发运行时异常-如果是这种情况,我希望编译器指示它们是只读的并抛出异常,但我不不知道这是否可能。

另一种方法是为每个集合/映射添加添加/删除并相应地更新 Length 属性 - 但同样,如果 MyOtherClass 中的值发生变化,MyClass 仍然不会知道它。

或者编写我自己的 Hashmap/List/Collection 以确定何时添加/删除项目,并且可能在 getMyOtherClass 上具有属性更改侦听器 getMyOtherClass2。

有什么好的解决方案吗?

谢谢,

安德斯

4

3 回答 3

1

在这种情况下,您可以利用观察者设计模式的一些基础知识让对象“监视”地图并注册对它们进行的每次更改。

创建一个包含 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 对象的观察者。

于 2012-08-17T12:36:24.890 回答
1

覆盖map/list实现并将回调插入到add/update/remove触发父更新函数的方法中。
直接创建对实现的引用也是一种不好的形式 - 这更好(阅读多态性以进行推理):

private Map<String,String> myMap = new HashMap<String,String>();
private List<String> myList = new List<String>();
于 2012-08-17T12:23:05.480 回答
0

不是 100% 确定你在问什么。如果您尝试跟踪两个类的属性更改,您可能希望,正如其他人提到的那样,实现观察者模式并在 set 方法中发出通知。我已成功用于实现撤消机制的另一种方法是使用 aspectJ 或其他一些 AOP(面向方面​​编程)工具来拦截 set 方法并以这种方式执行所需的通知/更新。

或者定义一个只提供对 getXXX 操作的访问并从您的模型中返回这些操作的接口,这样就不会更改数据。

于 2012-08-17T12:48:07.227 回答