策略模式的定义:
Define a family of algorithms, encapsulates each one, and make them interchangeable.
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换
策略模式三个角色:
Context封装角色:上下文角色,起承上启下的作用,屏蔽高层模块对策略,算法的直接访问,封装可能存在的变化
Strategy抽象策略角色:策略,算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
ConcreteStrategy具体策略角色:
//抽象的策略角色 public interface Strategy{ public void doSomething(); } //具体处理角色 public class ConcreteStrategy1 implements Strategy{ public void doSomething(){ //..... } } public class ConcreteStrategy2 implements Strategy{ public void doSomething(){ //..... } } //策略模式的重点在于封装角色,它是借用了代理模式的思路 //差别在于策略模式的封装角色和被封装策略类不用同一个接口 //如果是同一接口就成了代理模式 //封装角色 public class Context{ private Strategy strategy=null; public Context(Strategy _strategy){ this.strategy=_strategy; } public void doAnything(){ this.strategy.doSomething(); } } //高层模块的调用就是实例对应的策略类的对象,然后将其放到封装角色中 public class Client{ public static void main(String[] args){ Strategy strategy=new ConcreteStrategy1(); Context context=new Context(strategy); context.doAnything(); } }
优点:
1.算法可以自由切换:只要实现了抽象策略,它就成为策略家族的一个成员,通过封装角色对其进行封装,保证对外提供“可自由切换”的策略
2.避免使用多重条件判断:
3.扩展性良好
缺点:
1.策略类数量增多:每一个策略都是一个类,复用的可能性很小,类数量增多
2.所有的策略类都需要对外暴露:上层模块必须知道有哪些策略,然后才能决定使用哪个策略
使用场景:
1.多个类只有在算法或行为上稍有不同的场景
2.算法需要自由切换的场景
3.需要屏蔽算法规则的场景
策略模式的注意事项:如果一个系统中的一个策略家族的具体策略数量超过4个,就要考虑使用混合模式
,解决策略类膨胀和对外暴露的问题,否则日后的系统维护难度就会增加。