介绍
策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
策略模式通过将算法与使用算法的代码解耦,提供了一种动态选择不同算法的方法。客户端代码不需要知道具体的算法细节,而是通过调用环境类来使用所选择的策略。
策略模式包含以下几个核心角色:
- 环境(Context):维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以通过依赖注入、简单工厂等方式来获取具体策略对象。
- 抽象策略(Abstract Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
- 具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。
代码实现
第一步:创建接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
第二步:创建实现接口的实体类
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
第三步:创建context类
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
第四步:使用 Context 来查看当它改变策略 Strategy 时的行为变化
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
第五步:输出结果
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
优点:
1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点:
1、策略类会增多。 2、所有策略类都需要对外暴露。
使用场景:
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。
3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项
如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
策略模式和模板方法有什么区别
- 首先,从定义来看,策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以相互替换。这样,算法的变化不会影响到使用算法的用户,因为算法被封装在独立的类中,使用算法的用户(即应用层)不会感知到算法已经被替换。而模板方法模式则是定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。它使得子类可以在不改变算法结构的前提下,重新定义算法的某些步骤。
- 其次,从适用场景来看,策略模式主要适用于多种算法可以互换的情况,比如在处理同一类型问题时,有多种处理方式,仅仅是具体行为有差别,或者需要安全地封装多种同一类型的操作。此外,当同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时,策略模式也非常有用。而模板方法模式则更适用于那些一次性实现一个算法的不变部分,并将可变部分留给子类实现的情况。在子类的视角中,公共部分被提取出来,集中到一个公共的父类中,避免了代码的重复。
- 最后,从对算法的控制权来看,模板方法模式对算法有更多的控制权,它定义了算法的骨架,子类只能在这个骨架的基础上进行修改和扩展。而策略模式则更加灵活,它允许客户根据需要选择和替换算法,对算法的依赖程度较低。