繁体   English   中英

依靠嵌套开关重构为策略模式的方法

[英]Method that relies on nested switch refactoring to Strategy pattern

我在为遇到的特定问题实施策略模式时遇到问题。

我基本上有一种方法可以在值之间进行比较。 除了两个值之外,此方法还依赖于两个附加参数来确定我应该进行的比较:运算符(等于,不等于,...)和类型(字符串,双精度)基本上是依赖于另一个切换的结果。

让我用一个例子澄清一下:

public enum Type {
    STRING,
    BOOLEAN,
    DOUBLE;
}
public enum Operator {
    EQUALS(new Type[] { Type.STRING, Type.BOOLEAN}),
    NOT_EQUALS(new Type[] { Type.STRING, Type.BOOLEAN});

    private Type[] allowedTypes;

    Operator(Type[] allowedTypes) {
        this.allowedTypes = allowedTypes;
    }

    public List<Type> getAllowedTypes() {
        return Arrays.asList(allowedTypes);
    }
}
public class Evaluator {
    public Boolean evaluate(String value1, String value2, Operator operator, Type type) {
        switch(operator) {
            case EQUALS:
                return doEqualComparison(value1, value2, type);
        }

        return null;
    }

    private Boolean doEqualComparison(String value1, String value2, Type type) {
        //code here to check if the params are correct (not null, etc)
        switch(type) {
            case STRING:
                return value1.equals(value2);
            case DOUBLE:
                return Double.parseDouble(value1) == Double.parseDouble(value2);
        }

        return null;
    }
}

和测试

public class EvaluatorTest {
    @Test
    public void testEvaluate() {
        Evaluator evaluator = new Evaluator();

        // check STRING
        Assert.assertTrue(evaluator.evaluate("100", "100", Operator.EQUALS, Type.STRING));
        Assert.assertFalse(evaluator.evaluate("100.00", "100", Operator.EQUALS, Type.STRING));

        // check DOUBLE
        Assert.assertTrue(evaluator.evaluate("100", "100", Operator.EQUALS, Type.DOUBLE));
        Assert.assertTrue(evaluator.evaluate("100.00", "100", Operator.EQUALS, Type.DOUBLE));
    }
}

这可以正常工作,但是拥有两个(基本上嵌套的)switch语句似乎不是一个很干净并且可以用于未来的解决方案,以防万一我们添加了很多类型和运算符,事情变得很讨厌,很快,所以我的第一个重构就是更改第一个切换(运营商)为策略

public class EqualComparisonStrategy implements ComparisonStrategy {
    @Override
    public Boolean compare(String value1, String value2, Type Type) {
        //HERE IS MY PROBLEM
        switch (conditionType) {
            case STRING:
                return value1.equals(conditionValue);
            case DOUBLE:
                return Double.parseDouble(value1) == Double.parseDouble(value2);
        }

        return null;
    }

    @Override
    public boolean accept(Operator operator) {
        return operator == Operator.EQUAL;
    }
}

尽管该解决方案还不错,但我想我也想外部化第二个开关(我的评论所在),但问题是它的实现依赖于第一个开关(操作员)。 我想到了工厂制造的StringEqualComparisonStrategy之类的东西,或者只是在accept方法中做了更多的事情

//snippet of the accept methode (instead of a factory)
@Override
public boolean accept(Operator operator, Type type) {
    return operator == Operator.EQUAL && type == Type.STRING;
}

但这会创建M * N个策略,并且很快就会失控(我大约有8个运算符,其中3种类型的结果在24个策略中)看到我希望这是一个将来的证明,这不是最好的解决方案IMHO。

我敢肯定必须有一种模式可以解决此问题,但是我没有看到它。 (我不是模式英雄)

有人可以帮忙吗?

当我读到您的问题时,想到的第一件事就是Decorator Pattern 您可以使用特定用例所需的功能来装饰一个非常基本的评估器。 尽管如此,您仍将需要相当数量的装饰器,但是如果操作正确,最终可能会得到一个非常灵活的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM