web-dev-qa-db-ja.com

java

数百行の以下のコードで特定のビジネスルールを実装する必要があります

if this
      then this
else if
      then this
.
. // hundreds of lines of rules
 else
      that

これを効果的に実装したり、すべての異なるルールに適用できるようにコードを再利用したりできるデザインパターンはありますか。以下のようなものを作成する仕様パターンについて聞いた

public interface Specification {

boolean isSatisfiedBy(Object o);

Specification and(Specification specification);

Specification or(Specification specification);

Specification not(Specification specification);
}


public abstract class AbstractSpecification implements Specification {

public abstract boolean isSatisfiedBy(Object o);

public Specification and(final Specification specification) {
 return new AndSpecification(this, specification);
}

public Specification or(final Specification specification) {
 return new OrSpecification(this, specification);
}

 public Specification not(final Specification specification) {
 return new NotSpecification(specification);
}
}

そして、Is、And、Orメソッドの実装ですが、これはif else(私の理解が間違っているかもしれません)を書くことを節約できないと思います...

If elseステートメントが非常に多いこのようなビジネスルールを実装する最善の方法はありますか?

編集:単なるサンプルexample.A、B、Cなどはクラスのプロパティです。これらとは別に、同様の多くの他のルールがあります。このための汎用コードを作成したいと思います。

    If <A> = 'something' and <B> = ‘something’ then
    If <C> = ‘02’ and <D> <> ‘02’ and < E> <> ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> = ‘02’ and <J> <> ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> <> ‘02’ and <J> = ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> = ‘02’ and <J> = ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> = ‘02’ and <J> <> ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> <> ‘02’ and <J> = ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> = ‘02’ and <J> = ‘02’  then:
        If <Q> = Y then
            'something'
        Else then 
            'something'
Else :
Value of <Z>
20
SCoder

ここで戦略パターンが役立つ場合があります。 条件付きロジックを戦略に置き換える を確認してください

9
vishal_aim

Command pattern または Factory pattern

コマンドパターンを使用して、新しいオプションを追加すると無限に大きくなる傾向のある厄介なswitch/ifブロックを置き換えることができます。

public interface Command {
     void exec();
}

public class CommandA() implements Command {

     void exec() {
          // ... 
     }
}
// etc etc

その後、Map<String,Command>オブジェクトとCommandインスタンスを入力します。

commandMap.put("A", new CommandA());
commandMap.put("B", new CommandB());

その後、if/else ifチェーンを次のように置き換えることができます。

commandMap.get(value).exec();

Factory Patternでは、ifさを処理し、豊富なifを隠すFactoryにif/switchを含めます。 Factory Patternのコード例

6
fortytwo

Rules Design Pattern http://www.michael-whelan.net/rules-design-pattern/ を確認してください。これは、指定したサンプルコードに非常に似ており、ルールが満たされているかどうかを判断するためのメソッドを定義するベースインターフェイスと、さまざまなルールごとの具体的な実装で構成されています。私の理解では、switchステートメントは、ルールの構成が満たされるか失敗するまで物事を評価する単純なループになります。

interface IRule {
    bool isSatisfied(SomeThing thing);
}

class RuleA: IRule {
    public bool isSatisfied(SomeThing thing) {
        ...
    }
}

class RuleB: IRule {
    ...
}

class RuleC: IRule {
    ...
}

構成ルール:

class OrRule: IRule {
    private readonly IRule[] rules;

    public OrRule(params IRule[] rules) {
        this.rules = rules;
    }

    public isSatisfied(thing: Thing) {
        return this.rules.Any(r => r.isSatisfied(thing));
    }
}

class AndRule: IRule {
    private readonly IRule[] rules;

    public AndRule(params IRule[] rules) {
        this.rules = rules;
    }

    public isSatisfied(thing: Thing) {
        return this.rules.All(r => r.isSatisfied(thing));
    }
}

// Helpers for AndRule / OrRule

static IRule and(params IRule[] rules) {
    return new AndRule(rules);
}

static IRule or(params IRule[] rules) {
    return new OrRule(rules);
}

Thingに対してルールを実行するサービスメソッド:

class SomeService {
        public evaluate(IRule rule, Thing thing) {
            return rule.isSatisfied(thing);
        }
    }

使用法:

// Compose a tree of rules
var rule = 
    and (
        new Rule1(),
        or (
            new Rule2(),
            new Rule3()
        )
    );

var thing = new Thing();

new SomeService().evaluate(rule, thing);

これもここで回答されました: https://softwareengineering.stackexchange.com/questions/323018/business-rules-design-pattern

5
bingles

Drools のようなルールエンジンが役立つかもしれません。ただし、これはデザインパターンではないため、これはあなたが探している答えではないかもしれません。しかし、IMO、あなたはそれを考慮する必要があります。 ルールエンジンを使用する必要がある場合 に関するすばらしい記事を次に示します。

1
Daniel Kaplan

設計パターンは、コードを読みやすくしたり、保守性を改善したりするのに役立ちますが、そのような数の条件を本当に評価する必要がある場合、IFステートメントは避けられません。

私は他の観点から問題を見ることを検討します(例:問題を解決するために100個の条件文が本当に必要ですか?) アルゴリズム を変更または改善しようとします

Expression Language は、各IFステートメントを表す文字列をプログラムで作成し、このツールを使用して結果を評価することができますが、特定の実行に関連する問題を解決する必要があるため、多少の助けになります各条件に関連付けられたロジック。

1

Pythonを使用した簡単な戦略デモ:

class Context(object):
  def __init__(self, strategy):
    self.strategy = strategy

  def execute(self, num1, num2):
    return self.strategy(num1, num2)

class OperationAdd(object):
  def __call__(self, num1, num2):
    return num1 + num2


class OperationSub(object):
  def __call__(self, num1, num2):
    return num1 - num2


if __name__ == '__main__':
  con = Context(OperationAdd())
  print "10 + 5 =", con.execute(10, 5)

  con = Context(OperationSub())
  print "10 - 5 =", con.execute(10, 5)
1
lancerex