Personally, I agree with Peter, but for the sake of argument, I have two more answers. I would recommend looking at the rules engine (e.g. Drools) to implement such a flexible business logic. They are designed so that update rules between variables are easily set and changed at will. They should also be quite effective.
Then, for DYI-er, here is a version inspired by Spring. The biggest drawback is that you get your dependencies as a list. You can easily use the HashMap, but then you lose the syntax security.
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); } } }
The corresponding applicationContext.xml will look like this:
<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>
For an additional loan, you can implement a bean post-processor for automatic calculation and installation of dependencies based on annotations. For example:
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; }
Pace
source share