1.策略模式角色组成
主要分为3个角色:
- 封装角色(Context):上层访问策略的入口,它持有抽象策略角色的引用。
- 抽象策略角色 (Strategy):提供接口或者抽象类,定义策略组必须拥有的方法和属性。
- 具体策略角色(ConcreteStrategyA、ConcreteStrategyB):实现抽象策略,定义具体的算法逻辑。
2.实战
//封装角色类
public class Context {
private Strange strange;
//初始化具体策略
public Context(Strange strange){
this.strange = strange;
}
//调用具体策略
public void doThing(){
strange.doSomeThing();
}
}
//抽象策略类
public interface Strange {
public void doSomeThing();
}
//策略实现类A
public class ConcreteStrangeA implements Strange{
@Override
public void doSomeThing() {
System.out.println("调用A");
}
}
//策略实现类B
public class ConcreteStrangeB implements Strange{
@Override
public void doSomeThing(){
System.out.println("调用B");
}
}
结果:
3.策略模式优缺点
优点:
- 良好的扩展性。增加一种策略,只要实现接口,写上具体逻辑就可以了。当旧策略不需要时,直接剔除就行。
- 良好的封装性。策略的入口封装在Context封装类中,客户端只要知道使用哪种策略就传哪种策略对象就可以了。
- 避免像简单工厂模式这样的多重条件判断。
缺点:
- 客户端必须了解策略组的各个策略,并且决定使用哪一个策略,也就是各个策略需要暴露给客户端。
- 如果策略增多,策略类的数量就会增加。
4.解决策略暴露问题(策略工厂)
//策略工厂模式
public class Context {
private Strange strange;
//调用具体策略
public void doThing(){
strange.doSomeThing();
}
public void factoryMethod(String strangeClass){
if(strangeClass.equals("A")){
strange = new ConcreteStrangeA();
}else if(strangeClass.equals("B")){
strange = new ConcreteStrangeB();
}else {
System.out.println("错误");
}
}
public static void main(String[] args) {
Context context = new Context();
context.factoryMethod("A");
context.doThing();
}
}
结果:
策略工厂缺点
对具体策略角色进行增删时必须要动封装角色的代码,不符合开闭原则。
策略枚举和反射机制对策略模式进行改良。但也不是开闭原则。