Подтвердить что ты не робот

Шаблон проектирования для реализации бизнес-правил с сотнями if else в java

Мне нужно реализовать определенные бизнес-правила с сотнями строк ниже кода

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

Есть ли у нас шаблон дизайна, который может эффективно реализовать это или повторно использовать код, чтобы он мог применяться ко всем различным правилам. Я слышал о Specification Pattern, который создает что-то вроде ниже

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 if (возможно, мое понимание неверно)...

Есть ли какой-либо лучший подход для реализации таких бизнес-правил, имеющих так много выражений if else?

EDIT: просто пример 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>
4b9b3361

Ответ 2

Вы можете использовать Шаблон команды или Factory шаблон.

Шаблон команды можно использовать для замены громоздких переключателей/блоков, которые имеют тенденцию расти неограниченно, когда вы добавляете новые параметры.

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 Шаблоне вы включаете свой if/switch в Factory, который заботится об уродстве и скрывает обилие ifs. Пример кода для Factory Шаблон.

Ответ 3

Вам следует ознакомиться с шаблоном разработки правил 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);
}

Какой-то сервисный метод, который запускает правило для вещи:

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

Шаблон проектирования может помочь вам сделать код более читабельным или улучшить его ремонтопригодность, но если вам действительно нужно оценить такое количество условий, то можно избежать исключений из IF.

Я бы рассмотрел проблему с другой точки зрения (например: действительно ли мне нужно сто условных операторов для решения проблемы?), и я попытаюсь изменить или улучшить алгоритм.

Язык выражений может помочь вам, потому что вы можете программно создать строку, представляющую каждый оператор IF, и оценить результат с помощью этого инструмента, но вам все равно придется решить проблему, связанную с выполнением конкретной логики, связанной с каждым условием.

Ответ 6

Простая демонстрация стратегии с помощью 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)