【設計模式.行爲型.策略模式】
一、說明
策略模式封裝了不同的實現,可以基於不同的策略標識選擇不同的執行策略,從而避免書寫過多的if...else,switch等語句,擴展時不需要改動原代碼,只需要擴招不同的策略實現即可,符合開閉原則。常常搭配工廠模式一起使用。
一、最基本的策略模式使用
定義策略接口,實際執行的策略通過設置上下環境類的方式調用不同的策略。
package com.fatsea.news.pattern.behavioral;
/**
* @Author: Chunhai.Hu
* @Date: 2021/4/28 17:41
* @Desc: 行爲型.策略模式
* @最基本的策略模式使用
*/
public class BaseStrategyTest {
public static void main(String[] args) {
// 策略環境實例
Context context = new Context();
// 使用策略A
IBaseStrategy baseStrategyA = new BaseStrategyA();
context.setStrategy(baseStrategyA);
baseStrategyA.strategyMethod();
// 使用策略B
IBaseStrategy baseStrategyB = new BaseStrategyB();
context.setStrategy(baseStrategyB);
baseStrategyB.strategyMethod();
}
}
// 策略抽象
interface IBaseStrategy {
void strategyMethod ();
}
// 具體策略類A
class BaseStrategyA implements IBaseStrategy {
@Override
public void strategyMethod() {
System.out.println("aliPay支付策略......");
}
}
// 具體策略類B
class BaseStrategyB implements IBaseStrategy {
@Override
public void strategyMethod() {
System.out.println("weChatPay支付策略......");
}
}
// 上下文環境類
class Context {
private IBaseStrategy strategy;
public Context() {
}
public Context(IBaseStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(IBaseStrategy strategy) {
this.strategy = strategy;
}
public void strategyMethod () {
strategy.strategyMethod();
}
}
二、促銷策略測試[策略+工廠+單例]
使用工廠模式初始化各個策略的單例,放入一個Map集合中,調用時根據標識獲取不同策略的實現執行。
package com.fatsea.news.pattern.behavioral;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: Chunhai.Hu
* @Date: 2021/4/30 16:14
* @Desc: 行爲型.策略模式.促銷策略測試[策略+工廠+單例]
*/
public class PromotionalStrategyTest {
public static void main(String[] args) {
// 使用工廠和枚舉類型調用
IPromotional strategy = PromotionalStrategyFactory.getPromotionalStrategy(PromotionalStrategyFactory.PromotionalKey.COUPON);
strategy.doPromotional();
// 使用上下文環境類調用
PromotionalActivity activity = new PromotionalActivity();
activity.doPromotional();
}
}
// 促銷抽象接口
interface IPromotional {
void doPromotional();
}
// 促銷手段:無(默認方式)
class EmptyStrategy implements IPromotional {
@Override
public void doPromotional() {
System.out.println("原價購買,無促銷手段");
}
}
// 促銷手段:團購
class GroupByStrategy implements IPromotional {
@Override
public void doPromotional() {
System.out.println("團購促銷.滿5人即可享受團購價");
}
}
// 促銷手段:返現
class CashBackStrategy implements IPromotional {
@Override
public void doPromotional() {
System.out.println("返現實付款的20%至付款賬戶");
}
}
// 促銷手段:優惠券
class CouponStrategy implements IPromotional {
@Override
public void doPromotional() {
System.out.println("使用優惠券抵扣");
}
}
// 上下文環境類:具體活動[如需要.可將活動也進行抽象]
class PromotionalActivity {
IPromotional strategy;
// 默認使用無優惠策略
public PromotionalActivity() {
this.strategy = new EmptyStrategy();
}
public PromotionalActivity(IPromotional strategy) {
this.strategy = strategy;
}
public void setStrategy(IPromotional strategy) {
this.strategy = strategy;
}
public void doPromotional () {
strategy.doPromotional();
}
}
// 策略生成工廠
class PromotionalStrategyFactory {
// 單例初始話所有促銷策略到PROMOTIONS中,或者使用初級工廠動態生成不同的Strategy
private static Map<PromotionalKey, Object> PROMOTIONS = new HashMap<PromotionalKey, Object>();
static {
PROMOTIONS.put(PromotionalKey.EMPTY, new EmptyStrategy());
PROMOTIONS.put(PromotionalKey.GROUPBY, new GroupByStrategy());
PROMOTIONS.put(PromotionalKey.CASHBACK, new CashBackStrategy());
PROMOTIONS.put(PromotionalKey.COUPON, new CouponStrategy());
}
// 默認爲public、static、final屬性
enum PromotionalKey {
EMPTY, GROUPBY, CASHBACK, COUPON
}
// 不傳時,採用無優惠策略
public static IPromotional getPromotionalStrategy() {
return (IPromotional) PROMOTIONS.get(PromotionalKey.EMPTY);
}
// 根據優惠標識獲取實際優惠策略
public static IPromotional getPromotionalStrategy(PromotionalKey key) {
return (IPromotional) PROMOTIONS.get(key);
}
}
三、支付策略測試[策略+工廠+單例]
模式與二中的模式一致,只是用在了不同的業務場景,上述是優惠策略,這個是支付策略。
package com.fatsea.news.pattern.behavioral;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: Chunhai.Hu
* @Date: 2021/4/30 17:22
* @Desc: 行爲型.策略模式.支付策略測試[策略+工廠+單例]
*/
public class PayStrategyTest {
public static void main(String[] args) {
// 生成訂單
Order order = new Order();
order.setTradeNo("JD079825648546845");
order.setPrice(1000);
order.setNum(5);
// 使用工廠和枚舉類型調用支付策略
IPayStrategy strategy = PayStrategyFactory.getPayStrategy(PayStrategyFactory.PayWay.GOOGLEPAY);
System.out.println(strategy.getVoucher(order));
System.out.println(strategy.verifyPayResult(order.getTradeNo()));
}
}
// 訂單類
@Data
class Order {
// 單號
private String tradeNo;
// 單價
private Integer price;
// 數量
private Integer num;
}
// 支付策略抽象
interface IPayStrategy {
// 獲取支付憑證,調起支付
String getVoucher (Order order);
// APP主動上報,校驗支付結果
String verifyPayResult (String tradeNo);
}
// 支付策略:支付寶
class AliPay implements IPayStrategy {
@Override
public String getVoucher(Order order) {
String result = "支付寶,訂單號:" + order.getTradeNo() +
",單價:" + order.getPrice() +
",數量:" + order.getNum() +
",總價:" + order.getPrice() * order.getNum();
return result;
}
@Override
public String verifyPayResult(String tradeNo) {
return "支付寶支付成功,單號" + tradeNo;
}
}
// 支付策略:微信支付
class WeChatPay implements IPayStrategy {
@Override
public String getVoucher(Order order) {
String result = "微信支付,訂單號:" + order.getTradeNo() +
",單價:" + order.getPrice() +
",數量:" + order.getNum() +
",總價:" + order.getPrice() * order.getNum();
return result;
}
@Override
public String verifyPayResult(String tradeNo) {
return "微信支付成功,單號" + tradeNo;
}
}
// 支付策略:谷歌支付
class GooglePay implements IPayStrategy {
@Override
public String getVoucher(Order order) {
String result = "谷歌支付,訂單號:" + order.getTradeNo() +
",單價:" + order.getPrice() +
",數量:" + order.getNum() +
",總價:" + order.getPrice() * order.getNum();
return result;
}
@Override
public String verifyPayResult(String tradeNo) {
return "谷歌支付成功,單號" + tradeNo;
}
}
// 支付策略生成工廠
class PayStrategyFactory {
// 單例初始化所有支付策略
private static Map<PayWay, IPayStrategy> payStrategyMap = new HashMap<PayWay, IPayStrategy>();
static {
payStrategyMap.put(PayWay.ALIPAY, new AliPay());
payStrategyMap.put(PayWay.WECHATPAY, new WeChatPay());
payStrategyMap.put(PayWay.GOOGLEPAY, new GooglePay());
}
// 默認爲public、static、final屬性
enum PayWay {
ALIPAY, WECHATPAY, GOOGLEPAY
}
// 默認使用支付寶
public static IPayStrategy getPayStrategy () {
return payStrategyMap.get(PayWay.ALIPAY);
}
// 根據PayWay返回不同的支付策略
public static IPayStrategy getPayStrategy (PayWay payWay) {
return payStrategyMap.get(payWay);
}
}