ifelse複数の文でJavaの代替設計

アウトライン

ifelseは、任意のプログラミング言語の重要な部分です。しかし、我々は我々のコードは、より複雑で保守が困難にif文のネストされたの多くを、書きます。

次は、ifelse書かれた声明の中でコードを単純化する方法を模索しましょう。

ケーススタディ

私たちは、多くの場合、ビジネス・ロジック、ロジックが関与する条件の数に遭遇し、それぞれが異なったアプローチが必要です。一例として、クラスに電卓。我々は、操作に応じて二つの数字を入力として演算子をとり、その結果を返すメソッドを有することになります。

public int calculate(int a, int b, String operator) {
    int result = Integer.MIN_VALUE;
 
    if ("add".equals(operator)) {
        result = a + b;
    } else if ("multiply".equals(operator)) {
        result = a * b;
    } else if ("divide".equals(operator)) {
        result = a / b;
    } else if ("subtract".equals(operator)) {
        result = a - b;
    }
    return result;
}
复制代码

我々はまた、それを実現するためにswitch文を使用することができます。

public int calculateUsingSwitch(int a, int b, String operator) {
    switch (operator) {
    case "add":
        result = a + b;
        break;
    // other cases    
    }
    return result;
}
复制代码

一般的な開発では、文はより大きく、より複雑になることができれば。複雑な条件がある場合に加えて、switch文は適合しません。

他の副作用は、意思決定構造を入れ子になった彼らは管理不能になるということです。私たちは、new演算子を追加する必要がある場合たとえば、私たちは、もし新しいステートメントを追加し、動作を実現しなければなりません。

復興

あなたは私たちが望む効果を達成するためにパターンを設計することができます。

ファクトリパターン

多くの場合、我々は構造をifelse遭遇、そして最終的には各支店で同様の動作を行います。これは、ファクトリメソッドは、ファクトリメソッドは、指定されたタイプのオブジェクトを戻し抽出し、特定のオブジェクトの挙動に基づいてアクションを実行する機会を提供します。

この例で、の方法を適用する単一のインターフェースで操作を定義してみましょう:

public interface Operation {
    int apply(int a, int b);
}
复制代码

入力としての2つの数の方法と結果を返します。さんが追加実行のためのクラスを定義してみましょう:

public class Addition implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}
复制代码

私たちは今、与えられた操作オペレータのインスタンスを返すファクトリクラスを実装します:

public class OperatorFactory {
    static Map<String, Operation> operationMap = new HashMap<>();
    static {
        operationMap.put("add", new Addition());
        operationMap.put("divide", new Division());
        // more operators
    }
 
    public static Optional<Operation> getOperation(String operator) {
        return Optional.ofNullable(operationMap.get(operator));
    }
}
复制代码

さて、電卓クラスは、我々は、アプリケーションおよび関連する操作のソースの数を取得するために工場を照会することができます:

public int calculateUsingFactory(int a, int b, String operator) {
    Operation targetOperation = OperatorFactory
      .getOperation(operator)
      .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
    return targetOperation.apply(a, b);
}
复制代码

この例では、ファクトリクラスに委託疎結合の責任をオブジェクト方法を見てきました。文はちょうど私たちの目的に反しているファクトリクラスにシフトしている場合でも、そこに入れ子にすることができます。

それとも、私たちは地図でリポジトリオブジェクトを維持することができます、あなたは迅速な検索のためのリポジトリを照会することができます。私たちが見てきたように、OperatorFactory#operationMapは、私たちの目的を果たします。また、実行時地図でそれらを初期化して見えるように設定することができます。

列挙型を使用します

地図の添加を使用することに加えて、我々はまた、特定のビジネス・ロジックをマークするために列挙型を使用することができます。その後、我々は、以下の場合にネストされたステートメントやスイッチのcase文でそれらを使用することができます。それとも、我々はオブジェクトとしてそれらを植えることができ、関連するビジネス・ロジックを実装するための戦略を開発します。

これがあればネストされた文の数を減らし、単一列挙値に委託責任。

我々はそれを達成することができます方法を見てみましょう。まず第一に、私たちは私たちの列挙を定義する必要があります。

public enum Operator {
    ADD, MULTIPLY, SUBTRACT, DIVIDE
}
复制代码

更なる計算のために、これらの値が異なるオペレータのタグであることを観察することができます。我々は常に文がケースを切り替えるが、私たちは自分自身を列挙するための論理的な代替手段を設計するために委託させた場合、またはネストされた中に異なる条件として、これらの値を使用するように選択することができます。

私たちは、値が各メソッドのために定義して計算されている列挙されます。例えば:

ADD {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
},
// other operators
 
public abstract int apply(int a, int b);
复制代码

そして、電卓クラスは、我々は、操作を実行する方法を定義することができます。

(int型B、オペレータオペレータINT)公衆のINTを計算{(a、b)はoperator.apply返します。}

今、私たちが使用できるOperator#valueOf()メソッドを呼び出すために文字列値演算子を変換する方法を:

@Test
public void test() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
    assertEquals(7, result);
}
复制代码

コマンドモード

これまでの説明では、我々は与えられたオペレータの正しいビジネス・オブジェクト・インスタンスに戻りファクトリクラスを使用することを見てきました。その後、ビジネス・オブジェクトには、電卓で計算を実行するために使用しました。

また、入力時に実行できるコマンドを受信するための電卓#の計算方法を設計することができます。これは、ネストされた場合のステートメントの別の代替の方法だろう。

私たちは、最初に私たちのコマンド・インタフェースを定義します。

public interface Command {
    Integer execute();
}
复制代码

次は、AddCommandを実装してみましょう:

public class AddCommand implements Command {
    // Instance variables
 
    public AddCommand(int a, int b) {
        this.a = a;
        this.b = b;
    }
 
    @Override
    public Integer execute() {
        return a + b;
    }
}
复制代码

最後に、私たちは電卓の新しい方法を導入し、コマンドの実行を受け入れてみましょう:

public int calculate(Command command) {
    return command.execute();
}
复制代码

次に、我々はAddCommandコールをインスタンス化することによって計算し、電卓#の計算方法にそれを送ることができます。

@Test
public void test() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(new AddCommand(3, 7));
    assertEquals(10, result);
}
复制代码

ルールエンジン

我々は最終的にはif文のネストされたの多くを書くとき、それぞれの条件は、ビジネス・ルールが正しいロジックに対処するために評価する必要がありますについて説明します。メインコードの複雑さから取得したそのようなルールエンジン。RuleEngineその結果に基づいて評価ルールとリターンが入りました。

式を処理するための一連の規則により、簡単なRuleEngine、RuleEngineを設計することにより、例を示しましょうし、選択されたルールの結果を返します。まず、ルールのインターフェイスを定義します:

public interface Rule {
    boolean evaluate(Expression expression);
    Result getResult();
}
复制代码

第二に、私たちはRuleEngineを達成してみましょう:

public class RuleEngine {
    private static List<Rule> rules = new ArrayList<>();
 
    static {
        rules.add(new AddRule());
    }
 
    public Result process(Expression expression) {
        Rule rule = rules
          .stream()
          .filter(r -> r.evaluate(expression))
          .findFirst()
          .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
        return rule.getResult();
    }
}
复制代码

受信RuleEngineオブジェクトの表現および結果を返します。さて、オペレータのセットとして設計されてみましょうExpressionクラスは、2つのIntegerオブジェクトで構成され、それが適用されます。

public class Expression {
    private Integer x;
    private Integer y;
    private Operator operator;        
}
复制代码

最後に、私たちは、カスタムの追加ルールのクラスを定義しましょう操作を追加指定する際、クラスにのみ評価されます。

public class AddRule implements Rule {
    @Override
    public boolean evaluate(Expression expression) {
        boolean evalResult = false;
        if (expression.getOperator() == Operator.ADD) {
            this.result = expression.getX() + expression.getY();
            evalResult = true;
        }
        return evalResult;
    }    
}
复制代码

私たちは、今式コールRuleEngineを使用します。

@Test
public void test() {
    Expression expression = new Expression(5, 5, Operator.ADD);
    RuleEngine engine = new RuleEngine();
    Result result = engine.process(expression);
 
    assertNotNull(result);
    assertEquals(10, result.getValue());
}
复制代码

結論

これらのデザインパターンを通して、あなたの実際のビジネスシナリオに基づいて、特定の決断かもしれ当社ifelse文の代替として使用することができます。

おすすめ

転載: juejin.im/post/5ceb8fb5e51d4510a37bab7b