策略模式(Strategy Pattern)是指定义了算法家族、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。策略模式使得算法可以在不影响到客户端的情况下发生变化,可以避免多重分支的if...else...和switch语句。
策略模式属于对象的行为模式。策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
这个模式涉及到三个角色:
1、环境(Context)角色:持有一个Strategy的引用。
2、抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
3、具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
public class Context { //持有一个具体策略的对象 private Strategy strategy; public Context(Strategy strategy){ this.strategy = strategy; } /** * 策略方法 */ public void doSomething(){ strategy.doStrategy(); } }
public interface Strategy { /** * 策略方法 */ public void doStrategy(); }
public class StrategyA implements Strategy { @Override public void doStrategy() { //相关的业务 System.out.println("StrategyA.doStrategy() ") ; } }
public class StrategyB implements Strategy { @Override public void doStrategy() { //相关的业务 System.out.println("StrategyB.doStrategy() ") ; } }
public class StrategyC implements Strategy { @Override public void doStrategy() { //相关的业务 System.out.println("StrategyC.doStrategy() ") ; } }
模拟一个支付场景使用策略模式。
public abstract class Payment { // 支付类型 public abstract String getName(); // 查询余额 protected abstract double queryBalance(String uid); // 扣款支付 public PayState pay(String uid, double amount) { if (queryBalance(uid) < amount) { return new PayState(500, "支付失败", "余额不足"); } return new PayState(200, "支付成功", "支付金额:" + amount); } }
public class AliPay extends Payment { public String getName() { return "支付宝"; } protected double queryBalance(String uid) { return 900; } }
public class WechatPay extends Payment { public String getName() { return "微信支付"; } protected double queryBalance(String uid) { return 256; } }
public class UnionPay extends Payment { public String getName() { return "银联支付"; } protected double queryBalance(String uid) { return 120; } }
public class PayState { private int code; private Object data; private String msg; public PayState(int code, String msg, Object data) { this.code = code; this.data = data; this.msg = msg; } public String toString() { return ("支付状态:[" + code + "]," + msg + ",交易详情:" + data); } }
public class PayStrategy { public static final String ALI_PAY = "AliPay"; public static final String UNION_PAY = "UnionPay"; public static final String WECHAT_PAY = "WechatPay"; public static final String DEFAULT_PAY = ALI_PAY; private static Map<String, Payment> payStrategy = new HashMap<String, Payment>(); static { payStrategy.put(ALI_PAY, new AliPay()); payStrategy.put(WECHAT_PAY, new WechatPay()); payStrategy.put(UNION_PAY, new UnionPay()); } public static Payment get(String payKey) { if (!payStrategy.containsKey(payKey)) { return payStrategy.get(DEFAULT_PAY); } return payStrategy.get(payKey); } }
public class Order { private String uid; private String orderId; private double amount; public Order(String uid, String orderId, double amount) { this.uid = uid; this.orderId = orderId; this.amount = amount; } public PayState pay() { return pay(PayStrategy.DEFAULT_PAY); } public PayState pay(String payKey) { //这样可以避免if..else的使用 Payment payment = PayStrategy.get(payKey); System.out.println("欢迎使用" + payment.getName()); System.out.println("本次交易金额为:" + amount + ",开始扣款..."); return payment.pay(uid, amount); } }
public class PayStrategyTest { public static void main(String[] args) { // 省略把商品添加到购物车,再从购物车下单 // 直接从点单开始 Order order = new Order("1", "10995122458", 324.45); // 开始支付,选择微信支付、支付宝、银联卡... // 每个渠道它支付的具体算法是不一样的 // 基本算法固定的 // 这个值是在支付的时候才决定用哪个值 System.out.println(order.pay(PayStrategy.ALI_PAY)); Order order2 = new Order("1", "10995122459", 1000); System.out.println(order2.pay(PayStrategy.WECHAT_PAY)); } }
欢迎使用支付宝
本次交易金额为:324.45,开始扣款...
支付状态:[200],支付成功,交易详情:支付金额:324.45
欢迎使用微信支付
本次交易金额为:1000.0,开始扣款...
支付状态:[500],支付失败,交易详情:余额不足