Ответ 1
Стратегический шаблон может быть полезен здесь. Проверьте Заменить условную логику со стратегией
Мне нужно реализовать определенные бизнес-правила с сотнями строк ниже кода
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>
Стратегический шаблон может быть полезен здесь. Проверьте Заменить условную логику со стратегией
Вы можете использовать Шаблон команды или 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 Шаблон.
Вам следует ознакомиться с шаблоном разработки правил 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
Что-то, что может помочь, это механизм правил, например Drools. Это не шаблон дизайна, поэтому, возможно, это не тот ответ, который вы ищете. Но ИМО, вы должны это учитывать. Вот хорошая статья о когда вы должны использовать механизм правил.
Шаблон проектирования может помочь вам сделать код более читабельным или улучшить его ремонтопригодность, но если вам действительно нужно оценить такое количество условий, то можно избежать исключений из IF.
Я бы рассмотрел проблему с другой точки зрения (например: действительно ли мне нужно сто условных операторов для решения проблемы?), и я попытаюсь изменить или улучшить алгоритм.
Язык выражений может помочь вам, потому что вы можете программно создать строку, представляющую каждый оператор IF, и оценить результат с помощью этого инструмента, но вам все равно придется решить проблему, связанную с выполнением конкретной логики, связанной с каждым условием.
Простая демонстрация стратегии с помощью 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)