Padrão de Design para implementar regras de negócios com centenas de if else em java
if this
then this
else if
then this
.
. // hundreds of lines of rules
else
that
temos algum padrão de design que possa efetivamente implementar isto ou reutilizar o código para que ele possa ser aplicado a todas as regras diferentes. Ouvi falar de Padrão de especificação que cria algo como abaixo
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);
}
}
e,em seguida, a implementação de Is, e, ou métodos, mas eu acho que isso não pode me salvar escrevendo o caso contrário(pode ser meu entendimento é incorreto)...
Existe qualquer melhor abordagem para implementar tais regras de negócio com tantas declarações se mais?
editar: apenas um exemplo.A,B, C etc são propriedades de uma classe.Para além destes, existem muitas outras regras semelhantes.Vou fazer um código genérico para isto.
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>
6 answers
Você pode usar padrão de Comando ou padrão de Fábrica.
O Padrão de comandos pode ser usado para substituir os comutadores pesados / se os blocos que tendem a crescer indefinidamente à medida que adiciona novas opções.
public interface Command {
void exec();
}
public class CommandA() implements Command {
void exec() {
// ...
}
}
// etc etc
Então constrói um objecto Map<String,Command>
e preenche-o com instâncias de comando:
commandMap.put("A", new CommandA());
commandMap.put("B", new CommandB());
Depois pode substituir a sua cadeia if / else por:
commandMap.get(value).exec();
EmFábrica padrão Você inclui o seu if / switch numa fábrica que leva cuidado com a fealdade e esconde a abundância de se. exemplo de código para Padrão de fábrica .
Algo que pode ajudar é um motor de regras como Baba. Não é um padrão de design, então esta pode não ser a resposta que você está procurando. Mas IMO, devias considerar isso. Aqui está um grande artigo sobre Quando você deve usar um motor de Regras.
Um padrão de design pode ajudá-lo a tornar o código mais legível ou a melhorar a sua manutenção, mas se você realmente precisar de avaliar tais números de condições, as declarações IF não podem ser evitadas.
Eu consideraria ver o problema de outro ponto de vista (por exemplo: eu realmente preciso de cem declarações condicionais para resolver o problema?) and I would try to change or to improve the algorithm.
Uma demonstração de estratégia simples com 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)
Você deve verificar se as Regras Padrão de Design http://www.michael-whelan.net/rules-design-pattern/. Parece muito semelhante ao código de exemplo que você deu e consiste de uma base de interface que define um método para determinar se uma regra é satisfeita e, em seguida, várias implementações concretas por regras diferentes. Pelo que sei, a sua declaração de troca transformar-se-ia numa espécie de loop simples que apenas avalia as coisas até a sua composição de regras estar satisfeita ou falha.
interface IRule {
bool isSatisfied(SomeThing thing);
}
class RuleA: IRule {
public bool isSatisfied(SomeThing thing) {
...
}
}
class RuleA: IRule {
...
}
class RuleC: IRule {
...
}
Regras De Composição:
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);
}
Um método de serviço que governa uma coisa.
classe SomeService {
avaliação pública (regra da regra, coisa) (
Regra do regresso.isSatisfied (coisa);
}
}
Utilização:
// Compose a tree of rules
var rule =
and (
new Rule1(),
or (
new Rule2(),
new Rule3()
)
);
var thing = new Thing();
new SomeService().evaluate(rule, thing);
Isto também foi respondido aqui: https://softwareengineering.stackexchange.com/questions/323018/business-rules-design-pattern