策略模式
类型:行为类
定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。
与模板方法模式的比较
策略模式与模板方法模式很像,区别在于客户端调用方法时,模板方法模式调用方法的主体是抽象模板类,策略方法调用方法的主体是上下文类(一个在抽象策略类和具体策略类外部的类)
模板模式一般只针对一套算法,注重对同一个算法的不同细节进行抽象提供不同的实现。而策略模式注重多套算法多套实现,在算法中间不应该有交集,因此算法和算法之间一般不会有冗余代码!
策略模式优缺点
优点:
- 横向扩展性好,灵活性高
缺点
- 客户端需要知道全部策略,若策略过多会导致复杂度升高
模板模式优缺点
优点:
- 可维护性好,纵向扩展性好
缺点
- 耦合性较高,子类无法影响父类公用模块代码
与建造者模式的区别
参考
策略模式和建造者模式
(1)建造者模式是创建型的,也就是说用来创建对象的,而策略模式属于行为型模式,通过将行为封装成对象来降低类之间的耦合度;
(2)策略模式的抽象类仅仅定义了一个算法接口,而建造者模式的抽象类则已经定义好了算法骨架或者过程的步骤,也就是说策略模式的各具体策略在实现上可以差之千里,但是建造者模式的具体建造者必须按照接口中定义好的骨架或步骤去实现;
(3)策略模式的StrategyContext类通过提供一个上下文环境来维护具体策略;而建造者模式的Director类则是封装了Product类的创建细节,便于客户端程序调用。
UML
包结构
strategy
策略基类
package 策略模式.strategy;
public abstract class Action {
public abstract void doAction();
}
具体策略类
package 策略模式.strategy;
public class Walk extends Action{
@Override
public void doAction() {
System.out.println("走起路来了");
}
}
----------------------------------------------
package 策略模式.strategy;
public class Jump extends Action{
@Override
public void doAction() {
System.out.println("跳起来了");
}
}
----------------------------------------------
package 策略模式.strategy;
public class Run extends Action{
@Override
public void doAction() {
System.out.println("跑起步来了");
}
}
----------------------------------------------
上下文类
package 策略模式.context;
import 策略模式.strategy.Action;
public class Context {
private Action action;
public void setAction(Action action){
this.action=action;
}
public void doAction(){
this.action.doAction();
}
}
客户端
package 策略模式.client;
import 策略模式.context.Context;
import 策略模式.strategy.Jump;
import 策略模式.strategy.Run;
import 策略模式.strategy.Walk;
public class Client {
public static void main(String[] args) {
Context actionContext = new Context();
System.out.println("-------------------");
actionContext.setAction(new Walk());
actionContext.doAction();
System.out.println("-------------------");
actionContext.setAction(new Jump());
actionContext.doAction();
System.out.println("-------------------");
actionContext.setAction(new Run());
actionContext.doAction();
System.out.println("-------------------");
}
}
效果
-------------------
走起路来了
-------------------
跳起来了
-------------------
跑起步来了
-------------------
Process finished with exit code 0
优点
- 策略模式提供了对 “开闭原则” 的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。
- 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式而是通过继承,这样算法的使用就和算法本身混在一起,不符合 “单一职责原则”,而且使用继承无法实现算法或行为在程序运行时的动态切换。
- 使用策略模式可以避免多重条件选择语句。多重条件选择语句是硬编码,不易维护。
- 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
- 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
- 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。