策略模式的概述
策略模式定义了一组算法,并且将算法封装在持有公共接口的独立类中,每一个算法具有平等性,客户端根据实际的业务选择最合适的算法,
同时,客户端可以轻松的置换任何一种算法。
策略模式的角色
策略模式是对于一组算法的封装,将算法本身与客户端相分离,达到把算法的本身与算法的责任分离开来,交给相对应的对象去管理,
常用的做法是,定义一个接口,同时将各个算法封装在该接口的实现类中,
策略模式涉及到的三种角色
1.上下文的角色(Context),客户端,也就是调用方,它持有策略的引用Strategy,
2.抽象策略角色(Strategy),定义一个该策略的策略接口或者抽象类,
3.具体策略角色(StrategyA、StrategyB、StrategyC....),封装了各个算法以及行为
策略模式的示例
首先我们编写ExampleContext ,代码如下,
1 package com.example; 2 3 public class ExampleContext { 4 5 //持有抽象的策略接口 6 private ExampleStrategy exampleStrategy; 7 8 //带策略的构造函数 9 public ExampleContext(ExampleStrategy exampleStrategy) { 10 this.exampleStrategy = exampleStrategy; 11 } 12 13 14 public void useStratrgy() { 15 exampleStrategy.doSomthing(); 16 } 17 18 19 20 public static void main(String[] args) { 21 ExampleContext context = new ExampleContext(new ExampleStrategyA()); 22 context.useStratrgy(); 23 } 24 }
下面我们创建一个策略接口ExampleStrategy,同时定义一个抽象方法doSomthing()
1 package com.example; 2 3 public interface ExampleStrategy { 4 5 public void doSomthing(); 6 }
接下来我们定义一组算法实现策略接口,ExampleStrategyA、ExampleStrategyB、ExampleStrategyC....
1 package com.example; 2 3 public class ExampleStrategyA implements ExampleStrategy { 4 5 @Override 6 public void doSomthing() { 7 //业务代码 8 } 9 }
1 package com.example; 2 3 public class ExampleStrategyB implements ExampleStrategy { 4 5 @Override 6 public void doSomthing() { 7 //业务代码 8 } 9 }
1 package com.example; 2 3 public class ExampleStrategyC implements ExampleStrategy { 4 5 @Override 6 public void doSomthing() { 7 //业务代码 8 } 9 }
策略模式的优点
1.策略模式定义了一组算法,使得客户端不必在去编写繁琐的ifelse,只要关注使用哪一种算法就可以
2.策略模式可以定义一个策略接口,同时抽取一个抽象类来实现该接口,在抽象类中可以提取一些公共的方法,其他的具体策略类可以继承
该抽象类,在必要时,可以overwrite抽象类中的方法。这有效的避免了出现许多公共的代码。
3.策略模式具有良好的扩展性。
策略模式的缺点
1.客户端必须要清楚知道各个具体算法,并且理解他们的区别,以便更好的选择一种更合适的算法,
2.具体的策略类会封装在一个单独的子类中,也就意味着,随着算法的增多,子类的数目也会跟着增多。
策略模式在JDK源码中的应用
1.TreeMap源码在维护红黑树时,客户端可以自定义比较器。
策略模式在生活中的应用
1.诸葛亮的锦囊妙计就是策略,每一个锦囊就是一个具体的策略,
2.旅游的出行方式,走路、坐车、自行车...就是一个具体的策略。
注意
一个系统中的有超过四种策略,我们会考虑使用混合模式,在之后我博客中我会详细讲到。