前言
? ? ? ? 這篇文章的業務背景是基于我的另一篇文章:
?
對接蘋果支付退款退單接口-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實現類處理即可
結語
? ? ? ? 總的來說邏輯并不復雜,至于這樣設計好不好每個人的看法就當不一樣了,我個人是覺得這樣的話可以統一很多邏輯,不需要后續的人員再參與,
? ? ? ? 不好的地方在于沒有專門研究過設計模式的人可能看起來會很復雜,但是只要寫好對應的文檔其實就可了
????????