一.什么是策略模式
定义:定义一组算法,将每个算法封装起来,并且使它们之间可以互相转换
二.类图
Context封装角色:
也叫做上下文角色,起承上启下封装作用
Strategy抽象策略角色:
策略、算法的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
ConcreteStrategy具体策略角色:
实现抽象策略中的操作,该类含有具体的算法
三.代码实现
1.抽象的策略角色Strategy
抽象出具体策略角色子类中共有的方法
1 public interface Strategy { 2 //策略模式的运算法则 3 public void doSomething(); 4 }
2.具体策略角色ConcreteStrategy1
封装的具体策略方法一
1 public class ConcreteStrategy1 implements Strategy { 2 @Override 3 public void doSomething() { 4 System.out.println("策略模式法则1"); 5 } 6 }
3.具体策略角色ConcreteStrategy2
封装的具体策略方法二
1 public class ConcreteStrategy2 implements Strategy{ 2 @Override 3 public void doSomething() { 4 System.out.println("策略模式法则2"); 5 } 6 }
4.封装角色
借用代理模式的思路
策略模式和代理模式的差距就是:策略模式的封装角色和被封装的策略类不是实现同一接口,而代理模式实现的是同一接口
1 public class Context { 2 //抽象策略 3 private Strategy strategy; 4 //构造函数设置具体策略 5 public Context(Strategy strategy){ 6 this.strategy = strategy; 7 } 8 //封装后的策略方法 9 public void doAnything(){ 10 strategy.doSomething(); 11 } 12 }
5.主函数
要想实现哪一个策略,首先利用多态new出对象
其次new出封装角色对象
最后使用new出的封装角色对象调用封装后的策略方法
1 public class Client { 2 public static void main(String[] args) { 3 //声明一个具体策略 4 Strategy strategy = new ConcreteStrategy1(); 5 //声明上下文对象 6 Context context = new Context(strategy); 7 //执行封装后的方法 8 context.doAnything(); 9 } 10 }
四.策略模式的优点
1.算法之间可以自由切换。只要实现抽象策略,它就成为抽象家族的一个成员,通过封装角色对其进行封装,保证对外提供“可自由切换”的策略
2.避免使用多重条件判断。若没有策略模式,系统无法通过其他方式知道何时使用哪种策略,只能通过if条件进行判断,大量代码冗余
3.扩展性良好。系统中增加新的策略时,只要实现接口就可以了
五.策略模式缺点
1.策略模式类数量多。每一个策略都是一个类,复用性小,类数量增多
2.所有策略模式都需要对外暴露。上层模块必须知道有哪些策略,然后才能决定使用哪一个策略,这与迪米特法则相违背,我只是使用了一个策略,我凭什么就要了解这个策略呢?那封装还有什么意义呢?这个缺点我们可以通过工厂方法模式、代理模式或享元模式修正
六.策略模式使用场景
1.多个类只有在算法或行为上稍有不同的场景
2.算法需要自由切换的场景
七.策略模式注意事项
如果一个系统中的一个策略家族的具体策略数量超过4个,则需要老驴使用混合模式解决策略类膨胀和对外暴露的问题,否则后期维护会很麻烦