Joh*_*n K 14 java design-patterns strategy-pattern
以下代码示例是从Wikipedia复制的Strategy模式的实现.我的完整问题是......
Wiki的main方法:
//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);
}
}
Run Code Online (Sandbox Code Playgroud)
图案件:
// 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);
}
}
Run Code Online (Sandbox Code Playgroud)
具体考虑上面的例子,Context类是多余的吗?
例如,我可以main通过使用除Context之外的现有类和接口来提出以下替代实现,它将完全相同.它仍然松散耦合.
((编辑:在这个简单的场景中,当我忽略Context类时,我是否会犯下未来的错误?))
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);
}
Run Code Online (Sandbox Code Playgroud)
以点的形式列出通过答案和评论发现的内容:
如果任何其他点是有用的或如果需要更正留下评论,我将相应地修改列表.
Joh*_*lla 16
顾名思义,这Context就是封装战略执行点的内容.如果没有这个,你就会赤身裸体Strategy,而现在的召唤班会承担额外的责任:知道什么时候打电话给Strategy自己.你的例子可能有点过于简单,在这种特殊情况下,我会说这Context不会让你太过分.
可能更好地说明a的有用性的示例Context更像是以下内容:
public class LoadingDock { // Context.
private LoadStrategy ls; // Strategy.
public void setLoadStrategy(LoadStrategy ls) { ... }
// Clients of LoadingDock use this method to do the relevant work, rather
// than taking the responsibility of invoking the Strategy themselves.
public void shipItems(List<ShippingItem> l) {
// verify each item is properly packaged \
// ... | This code is complex and shouldn't be
// verify all addresses are correct | subsumed into consumers of LoadingDock.
// ... | Using a Context here is a win because
// load containers onto available vehicle | now clients don't need to know how a
Vehicle v = VehiclePool.fetch(); // | LoadingDock works or when to use a
ls.load(v, l); // / LoadStrategy.
}
}
Run Code Online (Sandbox Code Playgroud)
请注意Strategy永远不会直接从外部客户端调用.仅shipItems使用策略,其后面的步骤的详细信息是黑盒子.这允许在Context不影响客户端的情况下调整策略的使用方式.例如,可以完全重新排序或调整(或完全删除)步骤以满足性能目标或其他目标 - 但对于客户端,外观界面shipItems()看起来完全相同.
请注意,另外,我们的例子Context中,LoadingDock可能改变其LoadStrategy在基于其内部状态的任何时间.例如,如果码头太满,也许它会切换到更积极的调度机制,让箱子更快地进入码头并进入卡车,这样做会牺牲一些效率(可能卡车不会像他们本来可以).