理系学生日記

おまえはいつまで学生気分なのか

Composite パターン・Strategy パターンでの比較ロジック

実際には Composite パターンと Strategy パターンの組み合わせで比較条件をいくらでも複雑にできるという例です。

例えば 入力パラメータ a, b, c によって、特定ブロックを実行するか否かが複雑に異なり得るロジックを実装するケースがあります。

public class A {

  public void complexLogic(Integer a, Double b, String c) {
    // blah blah blah

    // この complexCondition が、色々変わり得る
    if ( complexCondition(a, b, c) ) {
      // なんか実行する

    }
  }
}

こういうときに使うパターンとしては、以下のような Interface を切ることが挙げられます。

  public interface ComplexStrategy {
    public Boolean judge(Integer a, Double b, String c);
  }

そして、個々の条件をクラスとして実装していきます。

  public class StrategyA implements ComplexStrategy {

    @Override
    public Boolean judge(Integer a, Double b, String c) {
       // 複雑な判断ロジック
    }
  }

  public class StrategyB implements ComplexStrategy {

    @Override
    public Boolean judge(Integer a, Double b, String c) {
       // 複雑な判断ロジック
    }
  }

このままだと単純に Strategy パターンになると思いますが、ここのミソは、個々の ComplexStrategy を組み合わせる Strategy を定義すること。例えば、AND 条件、OR 条件などを以下のように構成します。

  public class AndStrategy implements ComplexStrategy {

    private ComplexStrategy[] strategies;

    public AndStrategy(ComplexStrategy... strategies) {
        this.strategies = strategies;
    }

    @Override
    public Boolean judge(Integer a, Double b, String c) {
        for (ComplexStrategy s : strategies) {
            if (!s.judge(a, b, c)) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }
  }

こういう仕掛けを入れておくと、AND、OR 条件をいくらでも複雑にすることができ、個々の ComplexStrategy の再利用性が向上します。

  A a = new A(
     new AndStrategy(
        new StrategyA(),
        new StrategyB(),
        new OrStrategy(
            new StrategyA(),
            new StrategyB()
        )
    ));
  a.complexLogic(a, b, c);
)