字段分配存储以供以后完成

时间:2011-06-04 06:01:08

标签: java class-design

我有两节课。第一个类有someField,第二个类需要更改,所以第一个类调用FirstClass.setSomeField(value)。第二个类不能在那一刻更改字段,因此它将此FutureChange存储到一个列表中,该列表将在稍后时间进行并应用必要的更改。该类必须以可以比较FutureChange的实例的方式存储它,即避免两次设置相同的字段,以及其他事项。

实施FutureChange的最佳方式是什么?通过反射,这很容易。问题是我将有数百个类,每个类都有很多字段。

我甚至尝试了一个带有字段名称开关的地图:

public class Example { 

    public static Integer number;
    public static String words;

    public static void main(String args[]) {
        Map<Field, Object> map = new HashMap<Field, Object>();
            // store modifications
        map.put(Field.number, new Integer(10));
        map.put(Field.words, "Words");
        // some time later
        for(Map.Entry<Field, Object> entry: map.entrySet()) {
            modify(entry.getKey(), entry.getValue());
        }
    }

    public static void modify(Field m, Object value) {
        switch(m){
        case number:
            number = (Integer) value;
            break;
        case words:
            words = (String) value;
            break;
        }
    }

    public enum Field {
        number,
        words;
    }
}

但这不是最有效的方式,并且随着课程变大而可能会被堵塞。有谁知道如何最好地实现这个?

更多代码:

public class Main {
    FirstClass a = new FirstClass();
    SecondClass b = new SecondClass();
    // Third, Fourth, etc.

    public static void main(String args[]) {
        while(true) {
            // run each, no modifications allowed
            a.run(); // may want to modify several variables of b
            b.run(); // same as above
            // end of all runs, now modify
            a.modifyAll();
            b.modifyAll();
        }
    }
}

如您所见,我必须在运行期间存储它,然后再执行。

存储匿名内部Callable并稍后调用将是完美的,但我需要检查它正在做什么,以便我可以比较两个并确定它们是否存在冲突。

1 个答案:

答案 0 :(得分:0)

我会按你的建议使用反射。这比直接应用更改要慢得多。如果您真的想要效率,最好将代码分成两个阶段/阶段,一个使用当前值,一个应用更改而不是尝试存储更改。

public class StoredChanges {
    private final Map<Object, Map<String, Object>> changes = new IdentityHashMap<Object, Map<String, Object>>();

    public void storeChange(Object o, String fieldName, Object value) {
        Map<String, Object> changedForObject = changes.get(o);
        if (changedForObject == null)
            changes.put(o, changedForObject = new LinkedHashMap<String, Object>());
        changedForObject.put(fieldName, value);
    }

    public void applyChanges() {
        for (Map.Entry<Object, Map<String, Object>> objectMapEntry : changes.entrySet()) {
            Object o = objectMapEntry.getKey();
            for (Map.Entry<String, Object> fieldChange : objectMapEntry.getValue().entrySet()) {
                String fieldName = fieldChange.getKey();
                try {
                    Method setter = o.getClass().getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
                    setter.invoke(o, fieldChange.getValue());
                } catch (Exception e) {
                    e.printStackTrace(); // or log it.
                }
            }
        }
        changes.clear();
    }
}