场景的最佳设计模式

时间:2013-11-18 11:08:08

标签: java design-patterns

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

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

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

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

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

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

    if(查询缓存以查看是否需要来自网页的人口) 做一点事 其他( - -) 做一点事 else(如果读取应该记录 - 从缓存中查找) 做点什么......

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

2 个答案:

答案 0 :(得分:2)

Chain of Responsibility Composite中的每个链接元素都可以做到这一点,但你必须花一些时间来配置运行时结构。

可能只是getValue()场景的复合或观察者(但听起来更像是复合词)。

编辑:

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

结束编辑

这是一个使用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;
            }

        };
    }


}

答案 1 :(得分:0)

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

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

这似乎是一种非常灵活的方法 - 我甚至通过引入InjectionContext实现了一个简单的依赖注入,{{1}}是一个线程安全的上下文,用于连接对象。

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