一、概述
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的类而变化。
二、适用性
1.许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
2.需要使用一个算法的不同变体。
3.使用算法的类不应该知道数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4.一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。 将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
三、参与者
1.Strategy 定义所有支持的算法的公共接口。Context使用这个接口来调用某个ConcreteStrategy定义的算法。
2.ConcreteStrategy实现Strategy接口实现某具体算法。
3.Context 用一个ConcreteStrategy对象来配置。 维护一个Strategy对象的引用。 可定义一个接口让Strategy访问它的数据。
四、类图
五、示例
Strategy
public interface Strategy {void method();
}
ConcreteStrategy
public class StrategyImplA implements Strategy{@Overridepublic void method() {System.out.println("这是第一个实现");}
}
public class StrategyImplB implements Strategy{@Overridepublic void method() {System.out.println("这是第二个实现");}
}
public class StrategyImplC implements Strategy{@Overridepublic void method() {System.out.println("这是第三个实现");}
}
Context
public class Context {private Strategy stra;public Context(Strategy stra) {this.stra = stra;}public void doMethod() {stra.method();}
}
自测
@Testpublic void strategyTest() {Context ctx = new Context(new StrategyImplA());ctx.doMethod();ctx = new Context(new StrategyImplB());ctx.doMethod();ctx = new Context(new StrategyImplC());ctx.doMethod();}
自测结果
Connected to the target VM, address: '127.0.0.1:7252', transport: 'socket'
这是第一个实现
这是第二个实现
这是第三个实现
Disconnected from the target VM, address: '127.0.0.1:7252', transport: 'socket'
六、实践
PayStrategy
/*** @author lyon* @createTime 2018年04月25日* @Description*/
public interface PayStrategy {/*** 支付*/void pay(BigDecimal money);/*** 申请退款*/void refund(BigDecimal money);/*** 查询退款*/void refundQuery();/*** 关闭订单*/void close();/*** 查询订单*/void query();
}
阿里支付相关-AliPayStrategy
/*** @author lyon* @createTime 2018年04月25日* @Description*/
@Service("AliPayStrategy")
public class AliPayStrategy implements PayStrategy {@Overridepublic void pay(BigDecimal money) {System.out.printf("支付宝支付了:%.2f元%n", money);}@Overridepublic void refund(BigDecimal money) {System.out.printf("支付宝申请退款:%.2f元", money);}@Overridepublic void refundQuery() {System.out.println("支付宝申请退款查询");}@Overridepublic void close() {System.out.println("支付宝关闭订单");}@Overridepublic void query() {System.out.println("支付宝查询订单");}
}
微信支付相关-WeChatPayStrategy
/*** @author lyon* @createTime 2018年04月25日* @Description*/
@Service("WeChatPayStrategy")
public class WeChatPayStrategy implements PayStrategy {@Overridepublic void pay(BigDecimal money) {System.out.printf("微信支付了:%.2f元%n", money);}@Overridepublic void refund(BigDecimal money) {System.out.printf("微信申请退款:%.2f元", money);}@Overridepublic void refundQuery() {System.out.println("微信申请退款查询");}@Overridepublic void close() {System.out.println("微信关闭订单");}@Overridepublic void query() {System.out.println("微信查询订单");}
}
建行龙支付
/*** @author lyon* @createTime 2018年04月25日* @Description*/
@Service("LongPayStrategy")
public class LongPayStrategy implements PayChannelStrategy {@Overridepublic void pay(BigDecimal money) {System.out.printf("建行龙支付支付了:%.2f元%n", money);}@Overridepublic void refund(BigDecimal money) {System.out.printf("建行龙支付申请退款:%.2f元", money);}@Overridepublic void refundQuery() {System.out.println("建行龙支付申请退款查询");}@Overridepublic void close() {System.out.println("建行龙支付关闭订单");}@Overridepublic void query() {System.out.println("建行龙支付查询订单");}
}
支付工厂
/*** @author lyon* @createTime 2018年04月26日* @Description*/
@Component
public class PayStrategyFactory {private PayStrategyFactory(){}private static Map<String, PayChannelStrategy> map = new ConcurrentHashMap<>();static {map.put("wechat", new WeChatPayStrategy());map.put("ali", new AliPayStrategy());map.put("long", new LongPayStrategy());}public static PayChannelStrategy getPayStrategy(String payType){return map.get(payType);}
}
自测
/*** @author lyon* @createTime 2018年04月25日* @Description*/
public class TestStrategy {@Resourceprivate PayStrategyFactory payStrategyFactory;@Testpublic void strategyTest() throws Exception {PayChannelStrategy payStrategy = payStrategyFactory.getPayStrategy("ali");if(null == payStrategy){throw new Exception( "支付类型为空") ;}BigDecimal money = new BigDecimal("12.01");payStrategy.pay(money);}
}
测试结果
Connected to the target VM, address: '127.0.0.1:11660', transport: 'socket'
支付宝支付了:12.01元
Disconnected from the target VM, address: '127.0.0.1:11660', transport: 'socket'