模式动机
完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。
在软件开发中也常常遇到类似的情况,实现某一个功能有多个途径,此时可以使用一种设计模式来使得系统可以灵活地选择解决途径,也能够方便地增加新的解决途径。
在软件开发中经常需要根据用户不同的操作,触发不一样的执行业务逻辑,例如,用户在支付的时候,用户可以选择银行卡支付、微信支付、支付宝支付等等操作,而每一种支付方式后台的业务处理都是不尽相同的。
模式定义
策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。
模式结构
Context: 环境类
Strategy: 抽象策略类
ConcreteStrategyA: 具体策略类
模式代码分析
我们抽象出一个具体的支付接口和支付方法
public interface AbstractPayHandler extends InitializingBean {
/**
* 实现具体的支付操作
*/
void pay();
}
银行卡支付策略
@Component
class CardPayHandle implements AbstractPayHandler {
@Override
public void pay() {
System.out.println("CardPayHandle.pay");
}
@Override
public void afterPropertiesSet() throws Exception {
PayFactory.register("card",this);
}
}
微信支付策略
@Component
class WeixinPayHandle implements AbstractPayHandler {
@Override
public void pay() {
System.out.println("WeixinPayHandle.pay");
}
@Override
public void afterPropertiesSet() throws Exception {
PayFactory.register("weixin",this);
}
}
策略注册工厂
public class PayFactory {
private static Map<String, AbstractPayHandler> strategyMap = new ConcurrentHashMap<>();
public static void register(String name, AbstractPayHandler handler){
strategyMap.put(name,handler);
}
public static AbstractPayHandler getInvokeStrategy(String name){
return strategyMap.get(name);
}
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class PayTest2 {
@Test
public void getPay(){
String name="weixin";
AbstractPayStrategy handler = PayFactory.getInvokeStrategy(name);
if( handler==null){
System.out.println("暂不支持该设计模式");
return ;
}
handler.pay();
}
}
测试结果
模式优缺点
策略模式的优点
策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
策略模式提供了管理相关的算法族的办法。
策略模式提供了可以替换继承关系的办法。
使用策略模式可以避免使用多重条件转移语句。
策略模式的缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
适用环境
在以下情况下可以使用策略模式:
如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
一个系统需要动态地在几种算法中选择一种。
如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。
模式的应用
(1) Java SE的容器布局管理就是策略模式应用的一个经典实例。