demo
/**
- 抽象策略角色
- 定义具体策略类需要实现的方法
/
public interface PayStrategy {
/*
- 假设会返回一个支付页面 *
- @return {@link String } 支付页面 */ public String toPayHtml(); } ```
具体策略角色
支付宝支付策略类
/**
* 具体策略角色
* alipay
*/
public enum AlipayStrategyImpl implements PayStrategy {
SINGLETON;
@Override
public String toPayHtml() {
return "假设是支付宝页面";
}
public static PayStrategy getSingleton() {
System.out.println("获取单例");
return SINGLETON;
}
}
微信支付策略类 ```java /**
- 具体策略角色
weixin pay */ public enum WexinPayStrategyImpl implements PayStrategy { SINGLETON ; @Override public String toPayHtml() { return “假设是微信支付页面”; }
public static PayStrategy getSingleton() { System.out.println(“获取单例”); return SINGLETON; } }
<a name="xCNFS"></a>
#### 一个常量
- 定义支付渠道 id 和具体实现策略类 class 的映射
- 也可以改为 支付渠道 id 和具体实现策略类类名的映射
- 也可以将类名存储在 db 中
```java
/**
* 支付策略枚举
* 对应 支付渠道id-具体的支付实现策略类 class
*/
public enum PayStrategyClassName {
ALIPAY_STRATEGY(1, AlipayStrategyImpl.class),
WEXINIPAY_STRATEGY(2, WexinPayStrategyImpl.class),
;
/**
* 渠道 id
*/
private int channelId;
/**
* 具体的支付实现策略类的 class
*/
private Class<? extends PayStrategy> className;
/**
* 根据 channelId 获取对应的策略实现类名
*
* @param channelId 支付渠道 id
* @return
*/
public static Class<? extends PayStrategy> getPayStrategy(int channelId) {
for (PayStrategyClassName payStrategyClassName: values()) {
if (payStrategyClassName.channelId == channelId) {
return payStrategyClassName.className;
}
}
return null;
}
PayStrategyClassName(int channelId, Class<? extends PayStrategy> className) {
this.channelId = channelId;
this.className = className;
}
public int getChannelId() {
return channelId;
}
public Class<? extends PayStrategy> getClassName() {
return className;
}
}
环境角色
会对获得的具体策略实现类对象进行缓存
- 减少并发问题,此处缓存了具体策略实现的单例对象
也可以在 map 的 get and set 进行锁
/**
* 1. 环境角色
*/
public final class PayStrategyFactory {
private PayStrategyFactory() {
}
/**
* 获取单例的方法名
*/
private static String targetMethodName = "getSingleton";
/**
* 缓存
*/
private static Map<String, PayStrategy> payStrategyMap = new ConcurrentHashMap<>(2);
/**
* 根据类名 获得 具体策略实现类
*
* @param className 具体策略实现类的类名
* @return {@link PayStrategy}
*/
public static PayStrategy getPayStrategy(String className) {
if (Objects.isNull(className) || "".equals(className)) {
return null;
}
if (Objects.isNull(payStrategyMap.get(className))) {
try {
// 反射获得具体策略实现类 class
Class<?> clz = Class.forName(className);
Method method = clz.getDeclaredMethod(targetMethodName);
// 调用获取单例的静态方法
PayStrategy payStrategySingletonInstance = (PayStrategy) method.invoke(null);
// 进行缓存
payStrategyMap.put(className, payStrategySingletonInstance);
System.out.println("缓存支付策略单例ing");
return payStrategySingletonInstance;
} catch (Exception e) {
// TODO start logger
e.printStackTrace();
return null;
}
} else {
System.out.println("从缓存中获取了支付策略单例");
return payStrategyMap.get(className);
}
}
}
调用和输出
调用 ```java public class PayService { public static void startPay(int channelId) {
// 1. 通过渠道 id 获得 类名称
Class<?> cLassName = PayStrategyClassName.getPayStrategy(channelId);
if (Objects.isNull(cLassName)) {
System.out.println("没有对应的支付渠道");
return;
}
// 策略 + 单例 获得具体策略实现类
PayStrategy payStrategy = PayStrategyFactory.getPayStrategy(cLassName.getName());
if (Objects.nonNull(payStrategy)){
System.out.println(payStrategy.toPayHtml());
} else {
System.out.println("没有对应的支付策略");
}
} }
class Main { public static void main(String[] args) { PayService.startPay(0); System.out.println(“==============”); PayService.startPay(1); System.out.println(“==============”); PayService.startPay(1); System.out.println(“==============”); PayService.startPay(1); System.out.println(“——————-“); PayService.startPay(2); System.out.println(“——————-“); PayService.startPay(2); } }
- 输出
```shell
没有对应的支付渠道
==============
获取单例
缓存支付策略单例ing
假设是支付宝页面
==============
从缓存中获取了支付策略单例
假设是支付宝页面
==============
从缓存中获取了支付策略单例
假设是支付宝页面
-------------
获取单例
缓存支付策略单例ing
假设是微信支付页面
-------------
从缓存中获取了支付策略单例
假设是微信支付页面
Process finished with exit code 0