定義
策略模式:指的是對象具備某個行爲,但是在不同的場景中,該行爲有不同的實現算法。
舉個幾個生活的例子,就是不同收入的人羣採用不同的稅率,登錄的不同方式,支付的不同方式;
在代碼我們也見過策略模式,如ArrayList的排序傳入的Comparator
ArrayList list = new ArrayList();
list.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//此處的本質就是一個策略
return 0;
}
});
示例代碼場景描述
用戶可以選擇不同類型的支付方式,有支付寶支付,微信支付,京東白條支付,銀聯支付,根據用戶選擇地不同支付方法,執行不同的支付方式的代碼。
源代碼
/**
* 支付接口
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:23
*/
public interface Pay {
public void pay(Order order);
}
/**
* 支付寶支付
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:22
*/
public class AliPay implements Pay {
public void pay(Order order) {
System.out.println("使用支付寶支付");
System.out.println(order);
}
}
/**
* 京東支付
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:22
*/
public class JDPay implements Pay {
public void pay(Order order) {
System.out.println("使用京東白條支付");
System.out.println(order);
}
}
/**
* 微信支付
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:22
*/
public class WechatPay implements Pay {
public void pay(Order order) {
System.out.println("使用微信支付");
System.out.println(order);
}
}
/**
* 銀聯支付
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:23
*/
public class UnionPay implements Pay {
public void pay(Order order) {
System.out.println("使用銀聯支付");
System.out.println(order);
}
}
/**
* 訂單類
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:24
*/
public class Order {
private String orderNo;
private double amount;
private String product;
public Order(double amount, String product) {
this.amount = amount;
this.product = product;
this.orderNo = ("NO." + System.currentTimeMillis() + System.nanoTime()).substring(0, 32);
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
@Override
public String toString() {
return "[商品名: " + product + " , 價格: ¥ " + amount + " , 訂單號:" + orderNo + " ]";
}
}
/**
* 支付類型
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:35
*/
public enum PayType {
ALI_PAY("AliPay"),
WECHAT_PAY("WechatPay"),
JD_PAY("JDPay"),
UNION_PAY("UnionPay");
private final String payType;
private PayType(String payType) {
this.payType = payType;
}
public String getPayType() {
return this.payType;
}
}
支付簡單工廠(switch 和反射兩種實現)
/**
* 支付簡單工廠
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:34
*/
public class PayFactory {
private Pay pay = null;
private PayFactory(PayType payType) {
//做法一:直接使用switch獲取到對應類型的支付對象
// switch (payType) {
// case ALI_PAY:
// pay = new AliPay();
// break;
// case JD_PAY:
// pay = new JDPay();
// break;
// case WECHAT_PAY:
// pay = new WechatPay();
// break;
// case UNION_PAY:
// pay = new WechatPay();
// break;
// }
try {
//做法二:利用反射獲取對應類型的支付對象
Class clazz = Class.forName(this.getClass().getPackage().getName() + "." + payType.getPayType());
pay = (Pay) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public static PayFactory getInstance(PayType payType) {
return new PayFactory(payType);
}
public void pay(Order order) {
pay.pay(order);
}
}
測試客戶端
/**
* 測試類
*
* @author Lenjor
* @version 1.0
* @date 2019-10-03 16:21
*/
public class Client {
public static void main(String[] args) {
Order order = new Order(999.99, "RedMi 7 pro");
PayFactory payFactory = PayFactory.getInstance(PayType.ALI_PAY);
payFactory.pay(order);
}
}
運行結果
總結
策略模式關心的是選擇不同,策略就不同,側重點是不同的選擇導致不同的策略。所以關鍵在於,把不同的算法(策略)封裝,使得不同的算法之間不會相互影響,當需要增加一種新的算法(策略)時,只需要新增一個新的策略類和一個枚舉值即可,不會影響到其他原有的策略。
設計模式從來都不會是單獨存在的,這裏除了使用到了策略模式,也使用到了簡單工廠模式,而工廠類持有一個Pay對象的引用,又有點像靜態代理的味道,只是這裏工廠類這裏沒有實現Pay接口。