Хранение поля назначения для последующего завершения - PullRequest
0 голосов
/ 04 июня 2011

У меня есть два класса.Первый класс имеет 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 голосов
/ 04 июня 2011

Я бы использовал отражения, как вы предложили.Это будет намного медленнее, чем применение изменений напрямую.Если вам действительно нужна эффективность, вам лучше разбить код на две фазы / стадии, одна из которых использует текущее значение, а другая - применяет изменения, а не пытается сохранить изменения.

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();
    }
}
...