一.策略模式定义
策略模式是指定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户,可以避免多重分支的if…else和switch语句
二.策略模式的应用场景
1.假如系统中有很多类,而他们的区别仅仅在于他们的行为不同.
2.一个系统需要动态地在几种算法中选择一种.
三.策略模式的优点
1.符合开闭原则
2.避免使用多重条件转移语句,如if…else…语句,switch语句
3.使用策略模式可以提高算法的保密性和安全性
四.策略模式的缺点
1.客户端必须知道所有的策略,并且自行决定使用哪一个策略类
2.代码中会产生非常多的策略类,增加维护难度
五.策略模式在jdk源码中的体现
1.Comparator接口中的compare()方法就是一个策略抽象实现
public interface Comparator<T> { int compare(T o1, T o2); ... }
Comparator抽象类下面有非常多的实现类,我们经常会把Comparator作为参数传入作为排序策略,例如Arrays类的parallelSort方法等
public class Arrays {
... public static <T> void parallelSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> cmp) {
...
}
...
}
还有TreeMap的构造方法
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
六.策略模式在Spring源码中的应用
1.Resource类
public interface Resource extends InputStreamSource {
boolean exists();
default boolean isReadable() {
return true;
}
default boolean isOpen() {
return false;
}
default boolean isFile() {
return false;
}
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(this.getInputStream());
}
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String var1) throws IOException;
@Nullable
String getFilename();
String getDescription();
}
我们虽然没有直接使用 Resource 类,但是我们经常使用它的子类,例如:
2.Spring的初始化,不同的类型的类采用不 同的初始化策略
首先有一个 InstantiationStrategy 接口,我们来看一下源码:
public interface InstantiationStrategy {
Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3) throws BeansException;
Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3, Constructor<?> var4, @Nullable Object... var5) throws BeansException;
Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3, @Nullable Object var4, Method var5, @Nullable Object... var6) throws BeansException;
}
顶层的策略抽象非常简单,但是它下面有两种策略 SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy,我们看一下类图:
打开类图我们还发现 CglibSubclassingInstantiationStrategy 策略类还继承了 SimpleInstantiationStrategy 类,说明在实际应用中多种策略之间还可以继承使用
二.代码实现思路
总体思路:
有这么一个场景,一个商场要做活动,活动有很多种策略,例如返优惠券策略,返现策略,送赠品策略,那我们就可以采用单例模式创建一个策略工厂,这个工厂里拥有一个策略的map,在静态代码块中初始化这个map,并提供一个根据key获取策略的方法,接着创建一个活动类.这个活动类中拥有一个策略接口的引用,利用构造方法传入,并在execute()方法中调用策略,在测试类中,创建一个活动类,传入对应的策略的key即可
再来一个场景,在支付过程中,我们可以选择用微信支付,支付宝支付,银联支付,京东支付等等,如果用户没有选择支付方式,那也会有一个默认的支付方式,实现思路如下:
1)创建一个支付的抽象类,定义每种支付方式的规范
2)创建各种支付方式,继承支付的抽象类
3)创建一个支付方式的管理类,里面拥有一个map,以及每个key的常量,在static中将所有的支付方式put进去
4)创建一个订单order类,在订单类中,拥有两个方法,一个是带参的pay(),一个是不带参的pay(),在带参的方法中,利用传入的payKey去支付方式管理类中获取对应的支付方式,在不带参的方法中采用默认的key去支付方式管理类中获取支付方式
5)测试
public class PayStrategyTest {
public static void main(String[] args) {
Order order = new Order("1","20180311001000009",324.45);
PayState pay = order.pay(PayStrategy.JD_PAY);
System.out.println(pay);
}
}