Esse padrão de estratégia Java tem uma classe de contexto redundante?
O exemplo de código a seguir é uma implementação do padrão de estratégiacopiado da Wikipedia. Minha pergunta completa segue ...
O Wikimain
método:
//StrategyExample test application
class StrategyExample {
public static void main(String[] args) {
Context context;
// Three contexts following different strategies
context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);
}
}
As peças de padrão:
// The classes that implement a concrete strategy should implement this
// The context class uses this to call the concrete strategy
interface Strategy {
int execute(int a, int b);
}
// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyA's execute()");
return a + b; // Do an addition with a and b
}
}
class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyB's execute()");
return a - b; // Do a subtraction with a and b
}
}
class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyC's execute()");
return a * b; // Do a multiplication with a and b
}
}
// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
private Strategy strategy;
// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}
Considerando especificamente o exemplo acima, é aContext
classe redundante?
Por exemplo, posso propor o seguinte substitutomain
implementação usando as classes e interface existentes, exceto Contexto e funcionará exatamente da mesma forma. Ainda está fracamente acoplado.
((Editar: Neste cenário simples, quando deixo de fora a classe Context,Eu vou estar cometendo um erro futuro? ))
public static void main(String[] args) {
IStrategy strategy;
// Three strategies
strategy = new ConcreteStrategyAdd();
int resultA = strategy.executeStrategy(3,4);
strategy = new ConcreteStrategySubtract();
int resultB = strategy.executeStrategy(3,4);
strategy = new ConcreteStrategyMultiply();
int resultC = strategy.executeStrategy(3,4);
}
Atualização resumidaListando em forma de ponto o que foi descoberto através de respostas e comentários:
O Contexto permite a variação de como a Estratégia composta é usada (por exemplo, o tempo de sua chamada). Diferentes contextos podem fazer um trabalho interno diferente antes e depois de chamar a estratégia dada.O contexto é uma "caixa preta" de alto nível. A lógica do Contexto pode mudar, também a Estratégia composta pode mudar (ou uma diferente usada) sem quebrar o cliente porque o cliente entende apenas como chamar o contexto.Embora eu tenha criado uma implementação alternativa do código de exemplo da Wikipedia, deixando de fora o Contexto, e embora tenha funcionado da mesma forma que o original, toda a situação foi simplificada (em ambos os casos) e minhas alterações significaram: 1. não é uma Estratégia padrão mais, 2. Sinto falta dos benefícios do espírito do padrão de estratégia que são mencionados aqui.Minha implementação alternativa usava o método principal como um Contexto, então eu poderia também manter o Contexto se simulando efetivamente. Ao criar um padrão de estratégia impuro, foi criada uma confusão. Eu não precisei reinventar a roda ou tentar ser mais inteligente (neste caso).Se qualquer outro ponto for útil ou se precisar de correção, deixe um comentário e modificarei a lista de acordo.