前言
通过策略模式,可以轻松消除程序中大量的if...else... 和switch语句。
定义
策略模式(Strategy Pattern)又叫也叫政策模式(Policy Pattern),它是将定义的算法家族、分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户。
策略模式最重要的一点是在执行的过程中只会选择一种逻辑进行执行,而不是用if...else提前判断执行哪种逻辑,策略模式大多情况下是为了解决硬编码的问题。
使用场景
- 假如系统中有很多类,而它们的区别仅仅在于它们的行为不同。
- 一个系统需要动态的在几种算法中选择一种。
- 需要屏蔽某种算法规则。
案例
JDK中的Comparator比较器,Comparator中最重要的方法是compare(T o1, T o2),该方法将o1与o2进行比较,如果值等于0,那么位置不变,如果大于0,那么就会升序,如果小于0,那么就会降序。
还有Arrays类,Array类中的parallesort(T[], Comparator<? super T> cmp)
代码
代码就以支付为例
策略类
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String UNION_PAY = "UnionPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String, Payment> payStrategy = new HashMap<>();
static {
payStrategy.put(ALI_PAY, new AliPay());
payStrategy.put(JD_PAY, new JdPay());
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);
}
}
AliPay 类
public class AliPay extends Payment {
@Override
public String getName() {
return "AliPay";
}
@Override
protected double queryBalance(String uid) {
return 900;
}
}
Payment 类
public abstract class Payment {
public abstract String getName();
public MsgResult pay(String uid, double amount) {
if (queryBalance(uid) < amount) {
return new MsgResult(500, "支付失败", "余额不足");
}
return new MsgResult(200, "支付成功", "支付金额" + amount);
}
protected abstract double queryBalance(String uid);
}
Order类
@Data
@NoArgsConstructor
@ToString
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 MsgResult pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey) {
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用" + payment.getName());
System.out.println("本次交易金额" + amount + ",开始扣款....");
return payment.pay(uid, amount);
}
}
Test
public class Test {
public static void main(String[] args) {
Order order = new Order("1", System.currentTimeMillis() + "", 123.456);
MsgResult pay = order.pay(PayStrategy.UNION_PAY);
System.out.println(pay);
}
}
总结
优点
1、策略模式符合开闭原则。
2、避免使用多重条件转移语句,如if...else... 语句、switch语句
3、使用策略模式可以提高算法的保密性和安全性。
缺点
1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类
2、代码中会产生非常多策略类,增加维护难道。