1.前言
本文以Alipay、wecatpay为示例
设模式的介绍在模板方法的时候已经说过了
↓↓↓↓↓↓↓
设计模式-模板方法(解决重复代码)_哪个设计模式是用于处理重复代码的-CSDN博客
策略模式是一种行为设计模式,它允许在运行时选择算法的行为。它将算法封装在独立的策略类中,使得它们可以相互替换,而不影响客户端代码。这种模式通过将算法的选择从客户端代码中分离出来,提供了更大的灵活性和可维护性。
在Java中,策略模式的设计理念可以通过以下步骤实现:
- 定义一个策略接口(或抽象类),该接口定义了所有具体策略类都必须实现的方法。
- 创建具体的策略类,实现策略接口,并提供具体的算法实现。
- 在客户端代码中,创建一个策略对象,并将其传递给需要使用算法的对象。
- 客户端对象使用策略对象来执行特定的算法。
解决在多种相似算法存在时,使用条件语句(如if...else)导致的复杂性和难以维护的问题。
2.示例
支付系统
假设:用户可以选择支付宝、微信、一些银行通道进行 h5支付、app支付、退款等等
客户端决定具体是什么支付 这里只做简单示例没有具体支付流程.
示例这里对普通策略做了一点增强 策略接口继承一个策略标识的接口 具体的策略类重写策略标识的方法 然后在客户端调用的时候 策略管理器通过beanName找到具体的实现
示例中涉及到枚举 可以看上文
上代码↓↓↓↓↓↓↓
策略对象管理器
import org.springframework.context.ApplicationContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* 描 述:策略对象管理器
* 创 建 者:wby
* 创建时间:2024/8/14 11:36
*/
public class StrategyManager {
public static ApplicationContext context;
private static final Map<Class<?>, Map<String, Object>> TYPE_CACHE = new HashMap<>();
private static final Map<Class<? extends Strategy>, Map<String, Object>> TYPE_Strategy_CACHE = new HashMap<>();
public static <T> T byName(Class<T> interfaceZ, String name) {
Map<String, Object> cacheMap = Optional.ofNullable(TYPE_CACHE.get(interfaceZ)).orElse(new HashMap<>());
final Object cacheBean = cacheMap.get(name);
if (cacheBean != null) {
return (T) cacheBean;
}
TYPE_CACHE.putIfAbsent(interfaceZ, cacheMap);
final Object bean = context.getBean(name, interfaceZ);
cacheMap.put(name, bean);
return (T) bean;
}
public static <T> T byStrategy(Class<? extends Strategy> iStrategyClass, String Strategy) {
Map<String, Object> cacheMap = Optional.ofNullable(TYPE_Strategy_CACHE.get(iStrategyClass)).orElse(new HashMap<>());
final Object cacheBean = cacheMap.get(Strategy);
if (cacheBean != null) {
return (T) cacheBean;
}
TYPE_Strategy_CACHE.putIfAbsent(iStrategyClass, cacheMap);
final Map<String, ? extends Strategy> beans = context.getBeansOfType(iStrategyClass);
Strategy bean = null;
for (Strategy beanX : beans.values()) {
if (Strategy.equals(beanX.strategy().toString())) {
bean = beanX;
break;
}
}
cacheMap.put(Strategy, bean);
return (T) bean;
}
}
策略标识
/**
* 描 述:策略标识
* 创 建 者:wby
* 创建时间:2024/8/14 11:36
*/
public interface Strategy<T> {
T strategy();
}
策略接口
/**
* 描 述:策略接口
* 创 建 者:wby
* 创建时间:2024/8/14 14:59
*/
public interface BankPaymentAPI extends Strategy<BankTypeEnum>{
default void h5Pay(String name){
System.out.println("未找到实现");
}
default void appPay(String name){
System.out.println("未找到实现");
}
default void payQuery(){
System.out.println("未找到实现");
}
default void refund(String name){
System.out.println("未找到实现");
}
}
alipay实现
/**
* 描 述:支付宝策略实现
* 创 建 者:wby
* 创建时间:2024/8/14 15:02
*/
@Service
public class AlipayStrategyAPI implements BankPaymentAPI {
@Override
public void h5Pay(String name) {
System.out.println(name + "使用支付宝支付买了一辆自行车");
//TODO 调用支付宝支付接口返回H5链接
}
@Override
public void appPay(String name) {
System.out.println(name + "使用支付宝支付买了一个iphone15");
//TODO 调用支付宝支付接口返回orderStr 获取签名后的业务数据
}
@Override
public void payQuery() {
System.out.println("调用支付宝支付结果查询接口");
//TODO 调用支付宝支付结果查询接口
}
@Override
public void refund(String name) {
System.out.println(name + "进行支付宝退款");
//TODO 调用支付宝退款接口
}
@Override
public BankTypeEnum strategy() {
return BankTypeEnum.ALIPAY;
}
wecat实现
/**
* 描 述:微信策略实现
* 创 建 者:wby
* 创建时间:2024/8/14 15:02
*/
@Service
public class WecatStrategyAPI implements BankPaymentAPI {
@Override
public void h5Pay(String name) {
System.out.println(name + "买了一个限量版的皮包");
//TODO 调用微信支付接口返回H5链接
}
@Override
public void appPay(String name) {
System.out.println(name + "为了睡的更香买了一个枕头");
//TODO 调用微信支付接口返回orderStr 获取签名后的业务数据
}
@Override
public void payQuery() {
System.out.println("调用微信支付结果查询接口");
//TODO 调用微信支付结果查询接口
}
@Override
public void refund(String name) {
System.out.println(name + "进行微信退款");
//TODO 调用微信退款接口
}
@Override
public BankTypeEnum strategy() {
return BankTypeEnum.WECAT;
}
}
测试
/**
* 描 述:策略模式测试
* 创 建 者:wby
* 创建时间:2024/8/14 16:33
*/
public class StrategyPattren {
public static void main(String[] args) {
BankPaymentAPI alipayService = StrategyManager.byName(BankPaymentAPI.class, BankTypeEnum.ALIPAY.getCode());
System.out.println("支付宝开始===================");
alipayService.h5Pay("小李");
alipayService.appPay("小锦");
alipayService.payQuery();
alipayService.refund("小李");
System.out.println("微信开始===================");
BankPaymentAPI wecatService = StrategyManager.byName(BankPaymentAPI.class, BankTypeEnum.WECAT.getCode());
wecatService.h5Pay("小解");
wecatService.appPay("小赵");
wecatService.payQuery();
wecatService.refund("小解");
//其他通道支付......
}
}
输出
支付宝开始===================
小李使用支付宝支付买了一辆自行车
小锦使用支付宝支付买了一个iphone15
调用支付宝支付结果查询接口
小李进行支付宝退款
微信开始===================
小解买了一个限量版的皮包
小赵为了睡的更香买了一个枕头
调用微信支付结果查询接口
小解进行微信退款
3.优缺点
优点
-
策略模式提供了对“开闭原则”的完美支持,用户可以在不 修改原有系统的基础上选择算法或行为,也可以灵活地增加 新的算法或行为。
-
策略模式提供了管理相关的算法族的办法。
-
策略模式提供了可以替换继承关系的办法。
-
使用策略模式可以避免使用多重条件转移语句。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一 定程度上减少对象的数量。
适用场景
如果在一个系统里面有许多类,它们之间的区别仅在于它们 的行为,那么使用策略模式可以动态地让一个对象在许多行 为中选择一种行为。
一个系统需要动态地在几种算法中选择一种。
如果一个对象有很多的行为,如果不用恰当的模式,这些行 为就只好使用多重的条件选择语句来实现。
不希望客户端知道复杂的、与算法相关的数据结构,在具体 策略类中封装算法和相关的数据结构,提高算法的保密性与 安全性。
4.总结
写代码时总会出很多的if…else,或者case。如果在一个条件语句中又包含了多个条件语句就会使得代码变得臃肿,维护的成本也会加大,而策略模式就能较好的解决这个问题
如果有更好的见解 欢迎大家评论