策略模式:
策略模式(Strategy Pattern)是指定义了算法家族并分别封装起来,让他们之间可以互相替换,此模式使用得算法的变化不会影响使用算法的用户。
应用场景:
(1)系统中有很多类,而他们的区别仅仅在于行为不同。
(2)一个系统需要动态地在几种算法中选择一种。
例如:大家都用过支付宝支付、微信支付、银联支付、以及京东白条支付。一个常见的应用场景就是大家在支付时会提示选择支付方式,如果用户未选择,系统会使用默认的支付方式进行结算。
使用策略模式模拟次业务场景。
创建 Payment 抽象类,定义支付规范和支付逻辑:
package com.xq.design.startegy.pay.payport; import com.xq.design.startegy.pay.PayState; 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); } }
分别创建具体的支付方式,支付宝支付类 AliPay:
package com.xq.design.startegy.pay; import com.xq.design.startegy.pay.payport.Payment; public class AliPay extends Payment { @Override public String getName() { return "支付宝"; } @Override protected double queryBalance(String uid) { return 900; } }
银联支付类 UnionPay :
package com.xq.design.startegy.pay; import com.xq.design.startegy.pay.payport.Payment; public class UnionPay extends Payment { @Override public String getName() { return "银联支付"; } @Override protected double queryBalance(String uid) { return 120; } }
京东白条支付类 JDPay:
package com.xq.design.startegy.pay; import com.xq.design.startegy.pay.payport.Payment; public class JDPay extends Payment { @Override public String getName() { return "京东白条"; } @Override protected double queryBalance(String uid) { return 500; } }
创建支付状态的包装类 PayState:
package com.xq.design.startegy.pay; 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); } }
创建支付策略管理类 PayStrategy:
package com.xq.design.startegy.pay.payport; import com.xq.design.startegy.pay.AliPay; import com.xq.design.startegy.pay.JDPay; import com.xq.design.startegy.pay.UnionPay; import com.xq.design.startegy.pay.WechatPay; import java.util.HashMap; import java.util.Map; public class PayStrategy { public static final String ALI_PAUY = "AliPay"; public static final String JD_PAY = "jdPay"; public static final String UNION_PAY = "UnionPay"; public static final String WECHAT_PAY = "WechatPay"; public static final String DEFAULT_PAY = ALI_PAUY; private static Map<String,Payment> payStrategy = new HashMap<String,Payment>(); static{ payStrategy.put(ALI_PAUY, new AliPay()); payStrategy.put(WECHAT_PAY, new WechatPay()); payStrategy.put(UNION_PAY, new UnionPay()); payStrategy.put(JD_PAY, new JDPay()); } public static Payment get(String payKey){ if(!payStrategy.containsKey(payKey)){ return payStrategy.get(payKey); } return payStrategy.get(payKey); } }
创建订单类 Order:
package com.xq.design.startegy.pay; import com.xq.design.startegy.pay.payport.PayStrategy; import com.xq.design.startegy.pay.payport.Payment; 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; } //完美的解决了 switch 过程,不需要再代码中写switch了,更不需要写 if ... else if public PayState pay(){ return pay(PayStrategy.DEFAULT_PAY); } public PayState pay(String paykKey) { Payment payment = PayStrategy.get(paykKey); System.out.println("欢迎使用" + payment.getName()); System.out.println("本次交易金额为:" + amount + ",开始扣款..."); return payment.pay(uid,amount); } }
测试代码如下:
package com.xq.design.startegy.pay; import com.xq.design.startegy.pay.payport.PayStrategy; public class PayStrategyTest { public static void main(String[] args) { Order order = new Order("1","202005130000001",326.5); /** * 开始支付,选择支付方式 * 每个渠道支付的具体算法是不一样的,基本算法是固定的 * 在支付的时候才决定这个值是用哪个 */ System.out.println(order.pay(PayStrategy.ALI_PAUY)); } }
结果如下:
策略模式的优缺点
策略模式有点如下:
(1)策略模式符合开闭原则。
(2)策略模式可避免使用多重条件语句,如 if...else 语句、switch语句。
(3)使用策略模式可以提高算法的保密性和安全性。
策略模式的缺点如下:
(1)客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
(2)代码中会产生非常多的策略类,增加了代码的维护难度。