如何在Java中实现具有内部依赖关系的惰性计算有状态类?
我正在编写一个金融计算类,它将有许多setter函数输入、一些私有中间值和一些getter函数作为输出如何在Java中实现具有内部依赖关系的惰性计算有状态类?,java,design-patterns,Java,Design Patterns,我正在编写一个金融计算类,它将有许多setter函数输入、一些私有中间值和一些getter函数作为输出 专用中间值仅取决于输入值 输出值(由公共getter访问)仅依赖于输入和中间值 最终,你可以把整个东西画成一个有点纠结的无环有向图,一边有一堆输入,最后流向右边的一堆输出 实现这个类的最佳方式是什么。我有一些特殊要求: 在可能的情况下,进行评估。当输入发生变化时,我们现在可以知道可能需要哪些输出 该类必须易于重新设计,因此需要某种声明性模型 理想情况下,我想说C依赖于A和B。如果在A或
- 专用中间值仅取决于输入值
- 输出值(由公共getter访问)仅依赖于输入和中间值
- 在可能的情况下,进行评估。当输入发生变化时,我们现在可以知道可能需要哪些输出
- 该类必须易于重新设计,因此需要某种声明性模型
是否有一个Java模式可以帮助我干净地实现这种计算器?您可以使用这样的模式
double[] inputs = { ... }
double[] previousInputs = { Double.NaN, etc }; // NaN is never equal.
double[] outputs =
public void update() {
if (!Arrays.equals(inputs, previousInputs)) {
recalculate(inputs, outputs);
copyTo(inputs, previousInputs);
}
}
就个人而言,我同意彼得的观点,但出于争论的考虑,我还有两个答案。我建议使用规则引擎(例如Drools)来实现这样灵活的业务逻辑。它们的设计使变量之间的更新规则易于设置和随意更改。他们也应该表现得相当出色 那么,对于DYI er来说,这是一个受春天启发的版本。最大的缺点是将依赖项作为一个列表。您可以轻松地使用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);
}
}
}
公共抽象类变量{
私人T值;
私有列表>();
私有列表>();
公共部门得不到{
返回当前值;
}
公共无效集(T newValue){
当前值=新值;
updateUpstream();
}
公共摘要T重新计算evalue(列表变量:上游){
变量。update();
}
}
私有void addUpstream(变量){
上游。添加(变量);
}
公共void setDependencies(列表变量){
变量。addUpstream(此);
}
}
}
相应的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>
为了获得额外的积分,您可以实现一个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();
}
}
公共类CVVariable扩展变量{
私人贪婪的;
私有变量b;
@依赖性
公共无效集a(可变集a){
这个a=a;
}
@依赖性
公共无效挫折(b变量b){
这个.b=b;
}
//如果你走这条路,你就不需要依赖列表了
公共整数重新计算值(){
返回a.get()+b.get();
}
}
您似乎遇到了某种实时流处理问题
看看推特。即使您决定不使用它,您也可以借用。中解释的一些概念。您可以通过创建可重新计算的未来价值来构建解决方案
public class Computation<T> {
private T value;
private Set<Computation<?>> usedBy;
public T getValue(Computation<?> getter) {
if (usedBy == null) {
// value was not computed
value = compute();
usedBy = new HashSet();
}
if (getter != null) {
// add a dependency
usedBy.add(getter);
}
return value;
}
protected T compute() {
// override when needed a lazily-computed value
return null;
}
public void setValue(T value) {
// invalidate this value
invalidate();
// set the new value
this.value = value;
usedBy = new HashSet();
}
public void invalidate() {
if (usedBy != null) {
for (Computation<?> c : usedBy) {
c.invalidate();
}
usedBy = null;
}
value = null;
}
}
public class Business {
private Computation<Integer> a = new Computation<Integer>();
private Computation<Integer> b = new Computation<Integer>();
private Computation<Integer> c = new Computation<Integer>() {
public Integer compute() {
return a.getValue(this) + b.getValue(this);
}
};
public void setA(int v) {
a.setValue(v);
}
public void setB(int v) {
b.setValue(v);
}
public int getC() {
return c.getValue(null);
}
}
公共类计算{
私人T值;
private SetSomething是这样的:将输入保存在一个非特定的容器中,如果调用了一个getter,则根据给定的输入和中间值创建一个策略对象,并让它计算SO对象作为结果。是的,这是有效的,我已经得到了类似的结果(使用null而不是NaNs)-但它不是声明性的。这是一种非常必要的方法,你不认为吗?这是真的。有时最简单的方法是最好的。你可以使它更声明性,但我会尽量避免在过程中使它更复杂。是的,这就是我想要的!关于语法的问题:在我们定义类membe的语句中r c-这条语句似乎定义了一个成员,同时覆盖了类中的一个方法-我以前从未见过这种语法。这种技术有名字吗?你能给我指出语言参考中的一些东西吗?我可以阅读更多内容吗?这是一个匿名类。更多信息:这项技术很神奇,如果项目规模扩大到这是我想要的东西。Twitter在他们的系统中的某个地方真的使用了这项技术吗?是的,Twitter目前使用这项技术来统计每个URL和域的用户点击量。这个视频演示应该会让你感兴趣。