策略是對算法的封裝,將不同的算法封裝到具有相同接口的獨立的類中,使算法本身和客户端分離開來,並且算法之間可以相互替換。
在策略模式中主要有以下幾種角色
- 上下文信息類(Context):用於存放和執行需要使用的具體策略類以及客户端調用的邏輯。
- 抽象策略類(Strategy):定義策略的共有方法。
- 具體策略類(ConcreteStrategy 等):實現抽象策略類定義的共有方法。
下面使用策略模式模擬一個我開發過程中的一個場景,在聚合支付中商户經常會綁定一些專門用於支付播報的盒子,我們稱它為雲播報,這些雲播報可能是不同廠商生產的,我們進行通知的時候由於廠商之間給的接口和調用方式也不同,所以我們把雲播報通知抽象為一個抽象策略,而每個具體廠商就是一個具體策略。
抽象策略
public interface CloudHornStrategy {
/**
* 發送消息
* @param body
* @return
*/
boolean sendMessage(CloudRequestBody body);
}
參數類
public class CloudRequestBody {
private static Map<Integer,String> channelMap = new HashMap<>();
static {
channelMap.put(1,"支付寶");
channelMap.put(2,"微信");
channelMap.put(3,"雲閃付");
channelMap.put(4,"數字人民幣");
}
/**
* 金額
*/
private Long money;
/**
* 通道
*/
private String channel;
public CloudRequestBody(Long money,int channel) {
this.money = money;
this.channel = channelMap.get(channel);
}
public Long getMoney() {
return money;
}
public String getChannel() {
return channel;
}
}
具體策略
public class LDCloudHornStrategy implements CloudHornStrategy{
@Override
public boolean sendMessage(CloudRequestBody body) {
//.....
//一些列組裝參數,數據處理,調用廠商接口
String msg = String.format("LD廠商推送:%s到賬%d元", body.getChannel(), body.getMoney());
System.out.println(msg);
return true;
}
}
@Override
public boolean sendMessage(CloudRequestBody body) {
//.....
//一些列組裝參數,數據處理,調用廠商接口
String msg = String.format("TY廠商推送:%s到賬%d元", body.getChannel(), body.getMoney());
System.out.println(msg);
return true;
}
}
通知上下文
public class PayNotifyContext {
private static Map<String,CloudHornStrategy> strategyMap = null;
static {
strategyMap = new HashMap<>();
strategyMap.put("LD",new LDCloudHornStrategy());
strategyMap.put("TY",new TYCloudHornStrategy());
}
private CloudHornStrategy strategy;
public PayNotifyContext(String horn) {
this.strategy = strategyMap.get(horn);
}
public void payNotify(CloudRequestBody body){
strategy.sendMessage(body);
}
}
支付客户端通知
public class PayClient {
public static void main(String[] args) {
//支付成功,回調通知接口
//獲取用户綁定了幾個雲播報分別是什麼類型
//比如説用户有三個雲播報....當然獲取的用户數據不可能只有用户用的雲播報品牌,其它用户信息我們暫且不管
String[] horns = new String[]{"TY","LD","LD"};
//假設支付了誤元
CloudRequestBody body = new CloudRequestBody(5L,1);
for (String horn:horns) {
new PayNotifyContext(horn).payNotify(body);
}
}
}
=====結果=====
TY廠商推送:支付寶到賬5元
LD廠商推送:支付寶到賬5元
LD廠商推送:支付寶到賬5元
當我們使用新的廠商的雲播報時我們只需要增加一個策略,然後再對應的集合中增加枚舉值即可,這樣對代碼的改動極小,符合開閉原則,並極大的解耦。