Лично я согласен с Питером, но ради аргументов у меня есть два других ответа. Я бы рекомендовал взглянуть на механизм правил (например, Drools) для реализации гибкой бизнес-логики, подобной этой. Они разработаны таким образом, чтобы правила обновления между переменными легко устанавливались и изменялись по желанию. Они также должны быть достаточно производительными.
Тогда, для DYI-er, вот вдохновленная Spring версия. Самый большой недостаток в том, что вы получаете свои зависимости в виде списка. Вы можете легко использовать HashMap, но тогда вы потеряете безопасность синтаксиса.
public abstract class Variable<T> {
private T currentValue;
private List<Variable<?>> dependencies = new ArrayList<Variable<?>>();
private List<Variable<?>> upstream = new ArrayList<Variable<?>>();
public T get() {
return currentValue;
}
public void set(T newValue) {
currentValue = newValue;
updateUpstream();
}
public abstract T recalculateValue(List<Variable<?>> dependencies);
private void update() {
set(recalculateValue());
}
private void updateUpstream() {
for(Variable<?> variable : upstream) {
variable.update();
}
}
private void addUpstream(Variable<?> variable) {
upstream.add(variable);
}
public void setDependencies(List<Variable<?>> dependencies) {
this.dependencies = dependencies;
for(Variable<?> variable) {
variable.addUpstream(this);
}
}
}
Соответствующее applicationContext.xml будет выглядеть так:
<bean id="A" class="com.app.AVariable"/>
<bean id="B" class="com.app.BVariable"/>
<bean id="C" class="com.app.CVariable">
<property name="dependencies">
<list>
<ref bean="A"/>
<ref bean="B"/>
</list>
</property>
</bean>
Для дополнительного кредита вы можете реализовать постпроцессор бина для автоматического расчета и установки зависимостей на основе аннотаций. Например:
public class CVariable extends Variable<Integer> {
private AVariable a;
private BVariable b;
@Dependency
public void setA(AVariable a) {
this.a = a;
}
@Dependency
public void setB(BVariable b) {
this.b = b;
}
//If you were going this route you wouldn't need the list of dependencies
public Integer recalculateValue() {
return a.get() + b.get();
}
}