0

発生している特定の問題に対する戦略パターンの実装に問題があります。

基本的に、値を比較するメソッドがあります。2 つの値とは別に、このメソッドは 2 つの追加パラメーターに依存して、どの比較を行うべきかを決定します: 演算子 (等しい、等しくない、...) と型 (文字列、二重)。基本的には、に依存するスイッチです。別のスイッチの結果。

例を挙げて明確にしましょう:

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));
    }
}

これは問題なく機能しますが、2 つの (本質的にネストされた) 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;
    }
}

その解決策は「あまりにも」悪いわけではありませんが、2番目のスイッチ(私のコメントがある場所)も外部化したいと思いますが、問題は、その実装が最初の(演算子)に依存していることです。ファクトリによって作成された 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 つの演算子を持ち、24 の戦略で結果が得られる 3 つのタイプがあります) これを可能な限り将来の証拠にしたいので、これは私見の最良の解決策ではありません。

この問題を解決するパターンがあるに違いないと確信していますが、私はそれを見ていません。(私はパターンヒーローではない)

誰か助けてくれませんか?

4

1 に答える 1