Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中实现具有内部依赖关系的惰性计算有状态类?_Java_Design Patterns - Fatal编程技术网

如何在Java中实现具有内部依赖关系的惰性计算有状态类?

如何在Java中实现具有内部依赖关系的惰性计算有状态类?,java,design-patterns,Java,Design Patterns,我正在编写一个金融计算类,它将有许多setter函数输入、一些私有中间值和一些getter函数作为输出 专用中间值仅取决于输入值 输出值(由公共getter访问)仅依赖于输入和中间值 最终,你可以把整个东西画成一个有点纠结的无环有向图,一边有一堆输入,最后流向右边的一堆输出 实现这个类的最佳方式是什么。我有一些特殊要求: 在可能的情况下,进行评估。当输入发生变化时,我们现在可以知道可能需要哪些输出 该类必须易于重新设计,因此需要某种声明性模型 理想情况下,我想说C依赖于A和B。如果在A或

我正在编写一个金融计算类,它将有许多setter函数输入、一些私有中间值和一些getter函数作为输出

  • 专用中间值仅取决于输入值

  • 输出值(由公共getter访问)仅依赖于输入和中间值

最终,你可以把整个东西画成一个有点纠结的无环有向图,一边有一堆输入,最后流向右边的一堆输出

实现这个类的最佳方式是什么。我有一些特殊要求:

  • 在可能的情况下,进行评估。当输入发生变化时,我们现在可以知道可能需要哪些输出

  • 该类必须易于重新设计,因此需要某种声明性模型

理想情况下,我想说C依赖于A和B。如果在A或B发生变化后请求C,那么它将知道需要重新计算tht C,否则C将永远不需要刷新


是否有一个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和域的用户点击量。这个视频演示应该会让你感兴趣。