一、模式本質
1?策略模式:行為的選擇
核心思想:定義一組算法,將每個算法封裝起來,并使它們可以互相替換,讓算法的變化獨立于使用它的客戶端。
2?適配器模式:接口的轉換
核心思想:將一個類的接口轉換成客戶端期望的另一個接口,使原本因接口不兼容而無法協同工作的類能夠協同工作。
二、策略模式應用
1、策略模式模擬商品折扣算法
? ? ? Vip折扣、促銷折扣、滿減折扣
2、策略實現
2.1定義策略接口
public?interface?DiscountStrategy?{
? ??BigDecimal?calculateDiscount(Order?order);
}
2.2vip折扣
@Service("vipDiscount")
public?class?VipDiscountStrategy?implements?DiscountStrategy?{
? ??@Override
? ??public?BigDecimal?calculateDiscount(Order order) {
? ? ? ??return?order.getAmount().multiply(BigDecimal.valueOf(0.9));?
? ?}
}
2.3促銷折扣
@Service("promotionDiscount")
public?class?PromotionDiscountStrategy?implements?DiscountStrategy?{
? ??@Override
? ??public?BigDecimal?calculateDiscount(Order order) {
? ? ? ??return?order.getAmount().multiply(BigDecimal.valueOf(0.8));?
? ? }
}
2.4滿減折扣
@Service("fullReductionDiscount")
public?class?FullReductionDiscountStrategy?implements?DiscountStrategy?{
? ??@Override
? ??public?BigDecimal?calculateDiscount(Order order) {
? ? ? ??if?(order.getAmount().compareTo(BigDecimal.valueOf(100)) >?0) {
? ? ? ? ? ??return?order.getAmount().subtract(BigDecimal.valueOf(20));?
? ? ? ? }
? ? ? ??return?order.getAmount();
? ? }
}
2.5策略核心
@Service
public?class?DiscountContext?{? ??private?final?Map<String,?DiscountStrategy> strategyMap;
? ? @Autowired? ??public?DiscountContext(Map<String,?DiscountStrategy> strategyMap) {? ? ? ??this.strategyMap?= strategyMap;? ? }
? ? public?BigDecimal?applyDiscount(String?strategyName, Order order) {? ? ? ??DiscountStrategy?strategy = strategyMap.get(strategyName);? ? ? ??if?(strategy ==?null) {? ? ? ? ? ??throw?new?IllegalArgumentException("未知折扣策略: "?+ strategyName);? ? ? ? }? ? ? ??return?strategy.calculateDiscount(order);? ? }}
2.6控制器調用
@RestController
@RequestMapping("/orders")
public?class?OrderController?{
? ??@Autowired
? ??private?DiscountContext?discountContext;
? ??@PostMapping("/calculate")
? ??public?BigDecimal?calculatePrice(@RequestParam?String?discountType,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??@RequestBody?Order order) {
? ? ? ??return?discountContext.applyDiscount(discountType +?"Discount", order);
? ? }
}
3、策略模式優勢
? ? 新增折扣策略只需添加新類
? ? 避免多層if-else判斷
? ? 策略算法可獨立測試
三、適配器模式應用
1、適配器模式模擬統一支付接口
? ? ? ?需要接入支付寶、微信支付和PayPal,但三家接口完全不同
2、適配器實現
2.1定義統一支付接口
public?interface?PaymentGateway?{
? ??PaymentResult?pay(BigDecimal?amount,?String?orderId);
}
2.2支付寶適配器
2.2.1原生接口
public?class?AlipayService?{? ??public?AlipayResponse?createPayment(AlipayRequest request) {? ? ? ??// 支付寶原生邏輯? ? }
}
2.2.2支付寶適配器
@Service
public?class?AlipayAdapter?implements?PaymentGateway?{
? ??private?final?AlipayService?alipayService;
? ??@Override
? ??public?PaymentResult?pay(BigDecimal amount,?String?orderId) {
? ? ? ??// 轉換參數
? ? ? ??AlipayRequest?request =?new?AlipayRequest(amount, orderId);
? ? ? ??// 調用原生接口
? ? ? ??AlipayResponse?response = alipayService.createPayment(request);
? ? ? ??// 轉換結果
? ? ? ??return?new?PaymentResult(
? ? ?? ? response.isSuccess(),?
??? ? ? response.getTransactionId()
? ? ? ? );
? ? }
}
2.3微信支付適配器
@Service
public?class?WechatPayAdapter?implements?PaymentGateway?{
? ??private?final?WechatPayService?wechatService;
? ??@Override
? ??public?PaymentResult?pay(BigDecimal amount,?String?orderId) {
? ? ? ??// 轉換并調用微信接口
? ? }
}
2.4Paypal支付適配器
@Service
public?class?PayPalAdapter?implements?PaymentGateway?{
? ??private?final?PayPalClient?paypalClient;
? ??@Override
? ??public?PaymentResult?pay(BigDecimal amount,?String?orderId) {
? ? ? ??// 轉換并調用PayPal接口
? ? }
}
2.5統一支付實現
@Service
public?class?PaymentService?{
? ??private?final?Map<String,?PaymentGateway> gateways;
? ??@Autowired
? ??public?PaymentService(List<PaymentGateway> gatewayList) {
? ? ? ??this.gateways?= gatewayList.stream()
? ? ? ? ? ? .collect(Collectors.toMap(
? ? ? ? ? ? ? ? g -> g.getClass().getSimpleName().replace("Adapter",?"").toLowerCase(),
? ? ? ? ? ? ? ??Function.identity()
? ? ? ? ? ? ));
? ? }
? ??public?PaymentResult?processPayment(String?gatewayType,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?BigDecimal amount,?String?orderId) {
? ? ? ??PaymentGateway?gateway = gateways.get(gatewayType);
? ? ? ??if?(gateway ==?null) {
? ? ? ? ? ??throw?new?IllegalArgumentException("不支持的支付方式: "?+ gatewayType);
? ? ? ? }
? ? ? ??return?gateway.pay(amount, orderId);
? ? }
}
3適配器模式優勢
? ?無需修改三方支付SDK
? ?統一支付接口簡化調用
? ?新增支付渠道只需添加適配器
四、對比
?
?五、如何正確選擇何種模式
1 選擇策略模式
需要動態選擇算法或行為
有多個相似類僅在行為上
有差異需要消除復雜的件語句
希望算法能夠獨立于客戶端變化
2 選擇適配器模式
需要使用現有類但其接口不符合要求
需要創建可復用的類與不兼容接口協同工作
需要統一多個獨立開發的模塊接口
需要兼容舊系統或第三方庫
3流程示意圖
?