前言
这篇文章的业务背景是基于我的另一篇文章:
对接苹果支付退款退单接口-CSDN博客
然后就是说设计模式是很开放的东西,可能我觉得合适,你可能觉得不合适,这里只是做下讨论,没有一定要各位同意的意思....
相关图文件
这里我先把相关的图文件放上来,可能看着会比较清晰点
代码逻辑
先把每个类的代码放上来一下,首先是接口
涉及java类
AppNotifyCommand(这个没啥好说的)
public interface AppNotifyCommand<T extends AppStoreNotifyDto> {//命令定义,可以参考官网//https://developer.apple.com/documentation/appstoreservernotifications/notification_typeString REFUND_COMMAND_NAME = "REFUND";String NOT_FOUND_COMMAND_NAME = "NOT_FOUND";/*** 获取命令名称* @return*/String getCommandName();/*** 执行命令* @param T*/String execute(T T);
}
AbstractAppNotifyCommand(抽象类,给子类继承的,还是比较有意义的)
@Slf4j
public abstract class AbstractAppNotifyCommand<T extends AppStoreNotifyDto> implements AppNotifyCommand<T>{@Overridepublic String getCommandName() {String commandName = doGetCommandName();if(StringUtil.isBlank(commandName)) {throw new IllegalArgumentException("commandName为空");}return commandName;}@Overridepublic String execute(T T) {try {return doExecute(T);} catch (Exception e) {log.error("执行具体命令时发生异常", e);throw new AppException("执行具体命令时发生异常", e);}}protected abstract String doGetCommandName();protected abstract String doExecute(T T) throws Exception;}
AppRefundCommand(退款处理类)
@Service
public class AppRefundCommand extends AbstractAppNotifyCommand<AppStoreNotifyDto> {@Overrideprotected String doGetCommandName() {return REFUND_COMMAND_NAME;}@Overrideprotected String doExecute(AppStoreNotifyDto appStoreNotifyDto) throws Exception{// //获取解密数据
// AppStoreDecodedPayloadDto appStoreDecodedPayloadDto = parseTransactionInfo(appStoreNotifyDto);
//
// //退款逻辑处理.....return "执行完成了";}
}
AppNotFoundCommand(找不到对应的处理命令时也写了一个处理类)
@Slf4j
@Service
public class AppNotFoundCommand extends AbstractAppNotifyCommand<AppStoreNotifyDto> {@Overrideprotected String doGetCommandName() {return NOT_FOUND_COMMAND_NAME;}@Overrideprotected String doExecute(AppStoreNotifyDto appStoreNotifyDto) throws Exception {log.info("目前{}的命令没有进行处理,返回空字符串", appStoreNotifyDto.getNotificationType());return "";}
}
上面的几个类都是基础类,没啥好说的,主要是下面这个类,维护了对外的接口,如下
@Service
@Slf4j
public class AppCommandComposite {@Resourceprivate List<AppNotifyCommand<AppStoreNotifyDto>> appNotifyCommandList;private Map<String, AppNotifyCommand<AppStoreNotifyDto>> appNotifyCommandMap;@PostConstructpublic void init() {appNotifyCommandMap = new ConcurrentHashMap<>();//循环放置数据for (AppNotifyCommand<AppStoreNotifyDto> appNotifyCommand : appNotifyCommandList) {appNotifyCommandMap.put(appNotifyCommand.getCommandName(), appNotifyCommand);}}/*** 执行命令* @param appStoreNotifyPayLoadDto* @return*/public String handleCommand(AppStoreNotifyPayLoadDto appStoreNotifyPayLoadDto) {try {//解密基础数据AppStoreNotifyDto appStoreNotifyDto = AppStoreReturnUtil.verifyAndGet(appStoreNotifyPayLoadDto.getSignedPayload());log.info("开始执行苹果的{}通知命令", appStoreNotifyDto.getNotificationType());//获取安全的执行器执行AppNotifyCommand<AppStoreNotifyDto> appNotifyCommand = appNotifyCommandMap.get(appStoreNotifyDto.getNotificationType());String result = safeAppNotifyCommand(appNotifyCommand).execute(appStoreNotifyDto);log.info("执行苹果的{}通知命令完成,返回的数据为{}", appStoreNotifyDto.getNotificationType(), result);return result;} catch (Exception e) {log.error("解析苹果加密数据失败", e);throw new AppException("解析苹果加密数据失败");}}//获取安全的执行器执行private AppNotifyCommand<AppStoreNotifyDto> safeAppNotifyCommand(AppNotifyCommand<AppStoreNotifyDto> appNotifyCommand) {if(appNotifyCommand == null) {return appNotifyCommandMap.get(AppNotifyCommand.NOT_FOUND_COMMAND_NAME);}return appNotifyCommand;}
}
设计亮点
主要在AppCommandComposite类上面,主要用到了如下的一些亮点设计
1. 基于Spring 容器功能收集 以下数据
@Resource
private List<AppNotifyCommand<AppStoreNotifyDto>> appNotifyCommandList;
2. 基于Spring Bean的生命周期初始化方法 @PostConstruct 收集到map里面去
private Map<String, AppNotifyCommand<AppStoreNotifyDto>> appNotifyCommandMap;
3. 对外提供handleCommand 方法, 逻辑如下
首先对数据进行解密, 这在另外一篇文章说了,这里就不赘述了
其次根据苹果返回的notificationType获取到具体的命令处理器
精华在于,获取不到的时候会返回AppNotFoundCommand进行处理,而我们可以打印日志,表明苹果发了哪些请求,到时如果需要处理可以添加AppNotifyCommand实现类处理即可
结语
总的来说逻辑并不复杂,至于这样设计好不好每个人的看法就当不一样了,我个人是觉得这样的话可以统一很多逻辑,不需要后续的人员再参与,
不好的地方在于没有专门研究过设计模式的人可能看起来会很复杂,但是只要写好对应的文档其实就可了