原文地址:https://zhanglei.blog.csdn.net/article/details/121376500
前言
有段时间没写技术文章了,一是因为工作太忙,再者因为本人文笔实在一般。最近终于闲下来,本着分享的目的将一些组件设计上的心得与大家分享。
本篇文章是基于原有一篇关于支付文章的进一步优化设计,所以在阅读本篇文章前还是建议先移步到那篇文章。
文章地址: 微信、支付宝、银联、Paypal 支付组件封装
描述
在封装支付接口时,需要面临各支付平台不同SDK集成的问题,有的支付第三方平台只通过sdk组件就可完成支付,像支付宝,但大部分的支付第三方平台需要先去调用服务端API接口获取支付需要的信息,拿到这些支付信息后,再去调用sdk组件完成支付,这类第三方有银联(需要获取tn交易流水号),微信(需要获取prepayData
)等。
为了以后的支付功能复用,想要设计一个支付组件,该组件整合并统一了这些第三方支付sdk的接口,以便给客户端快速集成。在设计支付组件的过程中就遇到上面提到的问题。 如何解决某些第三方需要请求一些数据后,再进行支付的问题 ? 试想一下如果将这些请求hardcode到组件中,显然能满足当前的功能,局限性也非常明显,只能适用当前的支付业务。 此时的支付组件会和网络组件藕合,不利于扩展及复用。
设计
如何解藕? 如何能让这些需要请求API的第三方不污染组件? 解藕的思想就是“抽离变化,并封装”
。 我们需要把不稳定的部分抽离出来,使其独自变化,不影响稳定的部分。 找到了方向, 如何抽离? 这里我们可以使用面向协议的编程的思想,将请求API的行为进行抽象。
伪代码:
//抽像一个协议, 协议定义一个获取支付信息的方法,调用接口是异步操作,所以返回的数据使用block返回
@protocol PayDataPrepareProtocol <NSObject>
@required
- (void)getPayData:(void(^)(id result, NSError *error))block;
@end
微信支付伪代码:
@interface WXPayPrepareData : NSObject <PayDataPrepareProtocol>
@property (nonatomic,strong) NSDictionary *requestParams;
@end
@implementation WXPayPrepareData
- (void)getPayData:(void(^)(id result, NSError *error))block {
//根据请求参数,使用网络层组件调用API,并返回预支付信息
block(result,nil);
}
@end
银联支付伪代码:
@interface UnionPayPrepareData : NSObject <PayDataPrepareProtocol>
@property (nonatomic,strong) NSDictionary *requestParams;
@end
@implementation UnionPayPrepareData
- (void)getPayData:(void(^)(id result, NSError *error))block {
//根据请求参数,使用网络层组件调用API,并返回预支付信息
block(result,nil);
}
@end
如何能将支付类型与预支付实现类之间建立联系呢?我们需要设计一个配置类来管理这种支付类型与预支付实现类的对应关系 。
支付配置的伪代码:
typedef NS_Enum(NSInteger, PayType) {
PayTypeForAlipay, //支付宝支付
PayTypeForWXPay, //微信支付
PayTypeForUPPay, //银联支付
}
@interface PayConfig: NSObject
//单例对象
+ (instancetype)config;
//添加获取预支付信息对应的策略类, 没有传递实例对象,避免未使用而造成的内存浪费
- (void)appendPrepayDataStrategy:(Class)strategyClass withPayType:(PayType)payType;
//判断是否存在指定类型对应的实现策略
- (BOOL)containsPrepayDataStrategyWithPayType:(PayType)payType;
//根据支付的枚举类型,获取预支付信息处理对象
- (id<PayDataPrepareProtocol>)getPrepayDataStrategyWithPayType:(PayType)payType;
@end
@interface PayConfig ()
@property (nonatomic,strong) NSMutableDictionary *strategyMap;
@end
@implementation PayConfig
//单例对象
+ (instancetype)config {
static PayConfig *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!_instance) {
_instance = [[PayConfig alloc] init];
}
});
return _instance;
}
//添加获取预支付信息对应的策略类, 没有传递实例对象,避免未使用而造成的内存浪费
- (void)appendPrepayDataStrategy:(Class)strategyClass withPayType:(PayType)payType {
if (!strategyClass) {
return;
}
//判断是否实现了协议
if (![strategyClass conformsToProtocol:@protocol(PayDataPrepareProtocol)]) {
return;
}
NSString *payTypeKey = [Utils convertPayTypeToString:payType]; //将枚举转成字符串
[self.strategyMap setObject:strategyClass forKey:payTypeKey];
}
//判断是否存在指定类型对应的实现策略
- (BOOL)containsPrepayDataStrategyWithPayType:(PayType)payType {
NSString *payTypeKey = [Utils convertPayTypeToString:payType]; //将枚举转成字符串
return !self.strategyMap[payTypeKey];
}
//根据支付的枚举类型,获取预支付信息处理对象
- (id<PayDataPrepareProtocol>)getPrepayDataStrategyWithPayType:(PayType)pa