【问题标题】:Best design pattern for a scenario场景的最佳设计模式
【发布时间】:2013-12-01 12:18:18
【问题描述】:

我们有一个名为 Variable 的类,它表示单值或复合值。例如,它可以保存一个整数、一个布尔值、一个字符串等......(单值)或一些可以是字符串列表、整数或其他变量的复合值。

  1. 我们序列化这些对象,并且在流中所有这些值都表示为字符串。每当我们序列化或反序列化时,都会发生类型转换。

  2. 还有一些可选功能或方法可以填充这些变量中的值。例如,您可以定义要从网页填充的变量 - 对于给定的变量,我们会查询缓存以了解是否应该从网页填充它。每当有人对变量执行 getValue() 时,我们都会填充该值。

  3. 我们还想跟踪一些变量的变化。例如,每当读取或更改变量的值时,我都可以选择记录或执行某些操作。

如您所见,这是一个层次结构,因为变量可以包含其他变量。我们想找到解决这个问题的最佳方法。

目前我们只有一个叫做变量的类,它有很多if/else条件,代码非常复杂。 例如,getValue() 代码执行以下操作:

if(查询缓存以查看是否需要从网页填充) 做一点事 别的( - -) 做一点事 否则(如果应该记录读取 - 从缓存中查找) 做点什么……

是否有任何模式来设计我的类,使我的网页逻辑中的所有人口都可以进入一个类,跟踪其他类中的逻辑,其他类中的类型转换逻辑等等......更具可读性。

【问题讨论】:

    标签: java design-patterns


    【解决方案1】:

    我不确定这是否回答了您的问题,但是,这可能会带来一些新的想法,这是我在类似情况下提出的:

    • 我将这些 DynamicVariables 命名为。动态变量可能具有默认值或由 lamda (Java 8)/匿名内部类(Java 8 之前)评估。
    • 每个变量都有一个评估上下文,并且只能在一个上下文中进行评估 - 即会话上下文或全局上下文。上下文相互回退并创建层次结构,即会话上下文回退到全局上下文。因此,默认变量常量或 lambda 值可以被 lambda 或上下文中定义的常量遮蔽。例如,在会话内部访问时,会话范围的变量会掩盖全局变量。

    这似乎是一种非常灵活的方法——我什至通过引入InjectionContext 实现了一个简单的依赖注入,这是一个线程安全的上下文,包含一个被连接的对象。

    您可能想看看我目前正在开发的部署工具中的an example of how this is used。配置管理和共享应用程序逻辑建立在这些变量之上。代码在bear.context 包下,但目前还很原始。

    【讨论】:

      【解决方案2】:

      Chain of Responsibility Composite 中的每个链式元素都可以完成它的工作,但是您必须花一些时间来配置运行时结构。

      可能只是 getValue() 场景的 Composite 或 Observer(但在我看来更像是 Composite)。

      编辑:

      有人可能会争辩说,下面的实现实际上是“责任链”的情况,因为复合变量会将设置值的责任委托给其子级。

      结束编辑

      这是一个使用 Observer 和 Composite 的简单示例。未经测试只是为了让您对解决方案有总体感觉...

      我还没有实现诸如序列化/反序列化之类的东西。

      在这个解决方案中,你有复合值和原子值,你可以添加一些观察者在设置值之前执行。

      package dk.asj.variables;
      
      public abstract class VariableBase {
      
          public interface Observer {
              void onSet(final Value val, final VariableBase var);
          }
      
          private Observer obs = null;
      
          public void setObserver(final Observer obs) {
              this.obs = obs;
          }
      
          public void setValue(final Value val) {
              if (obs != null) {
                  obs.onSet(val, this);
              }
              internalSetValue(val);
          }
      
          protected abstract void internalSetValue(final Value val);
      
          public abstract Value getValue();
      
      }
      
      package dk.asj.variables;
      
      import java.util.List;
      
      public interface Value {
      
          int getIntValue();
      
          String getStringValue();
      
          List<Value> getCompositeValue();
      
      }
      
      package dk.asj.variables;
      
      public class SimpleVariable extends VariableBase {
      
          private Value val = null;
      
          @Override
          protected void internalSetValue(final Value val) {
              this.val = val;
          }
      
          @Override
          public Value getValue() {
              return val;
          }
      
      
      }
      
      package dk.asj.variables;
      
      import java.util.ArrayList;
      import java.util.LinkedList;
      import java.util.List;
      
      public class CompoundVariable extends VariableBase {
      
          final List<VariableBase> children = new LinkedList<VariableBase>();
      
          public void addChild(final VariableBase c) {
              children.add(c);
          }
      
          @Override
          protected void internalSetValue(final Value val) {
              for (int i = 0; i < val.getCompositeValue().size(); ++i) {
                  children.get(i).setValue(val.getCompositeValue().get(i));
              }
          }
      
          @Override
          public Value getValue() {
              final List<Value> res = new ArrayList<Value>(children.size());
              for (final VariableBase var : children) {
                  res.add(var.getValue());
              }
              return new Value() {
      
                  @Override
                  public int getIntValue() {
                      throw new RuntimeException("This is a composite value");
                  }
      
                  @Override
                  public String getStringValue() {
                      throw new RuntimeException("This is a composite value");
                  }
      
                  @Override
                  public List<Value> getCompositeValue() {
                      return res;
                  }
      
              };
          }
      
      
      }
      

      【讨论】:

      • 这对我来说似乎更有用。你能详细说明一下吗?你有任何例子。如果我理解正确,行为应该由一系列类处理,但数据以复合格式排列?
      • 给你:示例实现。享受吧!
      • 您可以按原样使用示例,还是需要更多详细信息或说明如何扩展它以涵盖整个场景?
      • 我正在进行的项目实际上比我在这里提出的要复杂。您的回答实际上证实了我们的想法。
      • 好的,很高兴知道我能以某种方式提供帮助 :) 如果您有更多问题或问题要讨论,请告诉我。这是一个有趣的真实示例,说明 DP 如何帮助描述从相对较少的类型和最少的逻辑将它们联系在一起的复杂事物。
      猜你喜欢
      • 2011-05-09
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-31
      • 1970-01-01
      相关资源
      最近更新 更多