先聲明,這篇文章并非是講什么是繼承什么是工廠模式,而是根據(jù)我工作的實(shí)際場景和優(yōu)化思路做的總結(jié)
在鍵盤上鍵入正確地咒語,屏幕會活動、變幻,顯示出前所未有的也不可能存在的事物!
我先把所有版本文檔羅列到這里:
iOS-繼承-繼承的工廠設(shè)計(jì)模式-多任務(wù)需求v1.1
iOS-繼承-繼承的工廠設(shè)計(jì)模式-多任務(wù)需求v1.2
iOS-協(xié)議-協(xié)議的工廠設(shè)計(jì)模式-多任務(wù)需求v1.3
我先直接介紹下v1.2版本的產(chǎn)品需求:

看圖可知,對于版本v1.1中的需求,就新加了一個添加待辦事項(xiàng)和刪除待辦事項(xiàng)的邏輯,首先我說下為什么我們會有這種奇葩的需求產(chǎn)生,我們做的App全部是以模塊開發(fā),每個模塊都有各自功能,然后對接非常多的需求商,中間有實(shí)施者接入我們的模塊,然后給需求商,也就是說,我這里模塊可能有N多需求商的App在使用,這中間避免不了需求商的個性化需求,那么這個需求接口就是給他們自由添加刪除事項(xiàng)。
一開始在做這個需求的時候,我是完全在v1.1版本上面去做的添加,無非就是增加兩個接口給外部,他們實(shí)施者可以添加事情進(jìn)來,有添加就有刪除,很簡單的道理,添加的事項(xiàng)是在App打開的時候就給進(jìn)來的,那么相當(dāng)于每次App打開都會去添加這個事項(xiàng),但是或許我只是需要這個事項(xiàng)在第一次登陸才出現(xiàn),那么刪除接口就有用了。至于實(shí)施者是需要什么時候刪除,以及刪除的規(guī)則都是由他自己去定,我只提供邏輯。
在v1.1版本中,大家還記得我是使用的三個數(shù)組分別存儲各類數(shù)據(jù),在這里給自己留坑了:
坑1. 當(dāng)刪除事項(xiàng)的時候,你會發(fā)現(xiàn)很麻煩,你需要依次找到各個數(shù)組下面的值,依次刪除其中數(shù)據(jù),
坑2. v1.1版本的所有業(yè)務(wù)處理都是寫在我的YxxAppLoginWaitWorking.m中的,那么實(shí)施者每添加一個事項(xiàng)就需要在YxxAppLoginWaitWorking.m中寫代碼,這樣就違背了模塊化開發(fā)了。
對于這兩個坑,在我們小組討論后,優(yōu)化方案是這樣的:
1.將業(yè)務(wù)、網(wǎng)絡(luò)請求事項(xiàng)、手動加入事項(xiàng)、刪除事項(xiàng)全部分開處理
2.將三個數(shù)組取出,只用一個數(shù)組去做操作
具體看下面代碼和注釋:
- YxxAppLoginWaitWorking.h
#import <Foundation/Foundation.h>
@interface YxxAppLoginWaitWorking : NSObject
//初始化
+ (YxxAppLoginWaitWorking *)initAppLoginWaitWorking;
//調(diào)用業(yè)務(wù)邏輯
- (void)showAppLoginWaitWorking;
//手動添加事項(xiàng)
- (void)manualAddWaitWorking:(NSDictionary *)addWorking;
//手動刪除事項(xiàng)
- (void)deleteWaitWorking:(NSString *)eventId;
@end
- YxxAppLoginWaitWorking.m
@interface YxxAppLoginWaitWorkingDataListModel : HFModel
@property (nonatomic, strong) NSArray *taskList; /**< 信息列表 */
@end
@implementation YxxAppLoginWaitWorkingDataListModel
@end
@interface YxxAppLoginWaitWorking ()
//相比v1.1版本這里只保存模型數(shù)組
@property (nonatomic, copy) NSMutableArray *waitWorkingModelAry; /**< 保存事件模型 */
@end
@implementation YxxAppLoginWaitWorking
/**
* 數(shù)組懶加載
*/
- (NSMutableArray *)waitWorkingModelAry
{
if (!_waitWorkingModelAry) {
_waitWorkingModelAry = [NSMutableArray array];
}
return _waitWorkingModelAry;
}
/**
* 單例初始化
*/
+ (YxxAppLoginWaitWorking *)initAppLoginWaitWorking
{
static YxxAppLoginWaitWorking *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[YxxAppLoginWaitWorking alloc] init];
});
return sharedInstance;
}
/**
* 開始事項(xiàng)
*/
- (void)showAppLoginWaitWorking
{
//監(jiān)聽登陸態(tài)
[RACObserve([YxxAppContext instance], isLogin) subscribeNext:^(id x) {
if ([x boolValue]){
//添加本地手勢事項(xiàng)
NSDictionary *dict = @{@"eventId":@"事件5",@"eventPri":@"1011"};
//手動添加數(shù)據(jù)
[self manualAddWaitWorking:dict];
//網(wǎng)絡(luò)請求數(shù)據(jù)
[self requestWaitWorking];
}
}];
}
/**
* 手動添加待辦事項(xiàng)
*/
- (void)manualAddWaitWorking:(NSDictionary *)addWorking
{
YxxAppLoginWaitWorkingModel *loginWorkingModel=nil;
NSError *err;
//這里是手動加入的本地登陸事項(xiàng)
if (addWorking) {
if (addWorking[@"eventId"] || addWorking[@"eventPri"]) {
//去重操作,防止多次添加同一個事件
for (loginWorkingModel in self.waitWorkingModelAry) {
if ([loginWorkingModel.eventId isEqualToString:addWorking[@"eventId"]]) {
return;
}
}
loginWorkingModel = [MTLJSONAdapter modelOfClass:[YxxAppLoginWaitWorkingModel class] fromJSONDictionary:addWorking error:&err];
loginWorkingModel.waitWorkingType = waitWorkingManualAdd;
[self.waitWorkingModelAry addObject:loginWorkingModel];
}else{
LogError(@"取!手動加入的本地登陸事項(xiàng),為空或者缺少字段");
}
}
}
/**
* 手動刪除待辦事項(xiàng)(這里刪除只是排除在app沒有退出的情況,用戶重新登錄,而會再次處理待辦事項(xiàng))
*/
- (void)deleteWaitWorking:(NSString *)eventId
{
NSMutableArray *copyAry = [NSMutableArray arrayWithArray:self.waitWorkingModelAry];
for (YxxAppLoginWaitWorkingModel *deleteModel in self.waitWorkingModelAry) {
if ([deleteModel.eventId isEqualToString:eventId]) {
[self.waitWorkingModelAry removeObject:copyAry];
}
}
[self.waitWorkingModelAry removeAllObjects];
[self.waitWorkingModelAry addObjectsFromArray:copyAry];
[copyAry removeAllObjects];
}
/**
* 網(wǎng)絡(luò)請求
*/
- (void)requestWaitWorking
{
[request sendRequest:^(YxxRequestModel *requestModel, NSError *error) {
NSError *err;
YxxAppLoginWaitWorkingModel *waitWorkingModel=nil;
NSMutableArray *separationEvent = [NSMutableArray array];//存儲待辦事項(xiàng)接口下來的數(shù)據(jù),以方便只刪除此數(shù)據(jù)
if (error){
//接口失敗了,也要處理其他端口獲取的待辦事項(xiàng)
if (self.waitWorkingModelAry.count) {
[self eventProcessing];
}
LogError(@"接口請求失敗");
return;
}else{
id model = requestModel.dataModel;
if ([model isKindOfClass:[YxxAppLoginWaitWorkingDataListModel class]]) {
NSArray *taskList = ((YxxAppLoginWaitWorkingDataListModel *)model).taskList;
//判斷有數(shù)據(jù)才存數(shù)組
if (taskList.count) {
for (NSDictionary *dict in taskList) {
waitWorkingModel = [MTLJSONAdapter modelOfClass:[YxxAppLoginWaitWorkingModel class] fromJSONDictionary:dict error:&err];
//過濾缺少字段的情況
if (waitWorkingModel.eventPri && waitWorkingModel.eventId && waitWorkingModel.eventStep) {
waitWorkingModel.waitWorkingType = waitWorkingRequest;
[self.waitWorkingModelAry addObject:waitWorkingModel];
}else{
LogError(@"后臺數(shù)據(jù)缺少字段,待辦事項(xiàng)不做處理,謝謝");
}
}
}
// 代辦事項(xiàng)處理
[self eventProcessing];
}
}
}];
}
/**
* 待辦事項(xiàng)的事件處理邏輯
*/
- (void)eventProcessing
{
//判空處理
if (self.waitWorkingModelAry.count == 0) {
return;
}
// 取優(yōu)先級最高的,即eventPri最小的
YxxAppLoginWaitWorkingModel *minNumModel = self.waitWorkingModelAry[0];
for (YxxAppLoginWaitWorkingModel *model in self.waitWorkingModelAry) {
if ([model.eventPri integerValue] < [minNumModel.eventPri integerValue]) {
minNumModel = model;
}
}
//所有事項(xiàng)的父輩
YxxDoWaitWorkingBaseClass *doWaitWorking = [YxxDoWaitWorkingBaseClass createClichClassWithEventId:minNumModel.eventId];
[doWaitWorking startEvent:minNumModel];
// 做完待辦事項(xiàng)后,刪除
// 服務(wù)器代辦事項(xiàng)做完后,刪除服務(wù)器拿到的代辦事項(xiàng)
NSMutableArray *copyAry = [NSMutableArray arrayWithArray:self.waitWorkingModelAry];
for (YxxAppLoginWaitWorkingModel *deleteModel in self.waitWorkingModelAry) {
if (deleteModel.waitWorkingType == waitWorkingRequest || deleteModel.waitWorkingType == waitWorkingAccessLogin) {
[copyAry removeObject:deleteModel];
}
}
[self.waitWorkingModelAry removeAllObjects];
[self.waitWorkingModelAry addObjectsFromArray:copyAry];
[copyAry removeAllObjects];
}
@end
- YxxDoWaitWorkingBaseClass.h
@interface YxxDoWaitWorkingBaseClass : NSObject
/**
* 在編譯的過程中,子類的load方法調(diào)用,主要是得到一個字典存入數(shù)組中
*/
void registerWaitEvent(Class eventClass, NSString *eventPri);
/**
* 得到一個子類的類名
*/
NSString *classsNameStringWithEventId(NSString *eventPri);
/**
* 初始化
* eventId : 將優(yōu)先級最高的id傳入
*/
+(instancetype)createClichClassWithEventId:(NSString *)eventPri;
/**
* 類方法,子類在編譯的時候會存入事件的id
*/
+(NSString *)eventId;
/**
* 事件需要做得事情
*/
-(void)startEvent:(YxxAppLoginWaitWorkingModel *)model;
/**
* 清除待辦事項(xiàng)請求
*/
- (void)cancelWaitWorkingRequest:(NSString *)eventId;
@end
- YxxDoWaitWorkingBaseClass.m
#import "YxxDoWaitWorkingBaseClass.h"
#import "YxxRequest.h"
static NSMutableArray *eventIdAry;
/**
* 在編譯的過程中,子類的load方法調(diào)用,主要是得到一個字典存入數(shù)組中
*/
NSString *classsNameStringWithEventId(NSString *eventId){
if (eventIdAry.count) {
for (NSDictionary *dict in eventIdAry) {
NSArray *eventIdKeyAry = [dict allKeys];
if ([eventIdKeyAry[0] isEqualToString:eventId]) {
return dict[eventIdKeyAry[0]];
}
}
}else{
return nil;
}
}
@implementation YxxDoWaitWorkingBaseClass
//根據(jù)出入的優(yōu)先級找到對應(yīng)事項(xiàng),然后返回對應(yīng)事項(xiàng)子類
+(instancetype)createClichClassWithEventId:(NSString *)eventPri
{
NSString *className = classsNameStringWithEventId(eventPri);
if (className) {
return [[NSClassFromString(className) alloc] init];
}
return nil;
}
void registerWaitEvent(Class eventClass, NSString *eventId){
if (eventId == nil) {
return;
}
if (eventIdAry == nil) {
eventIdAry = [NSMutableArray array];
}
[eventIdAry addObject:@{eventId:NSStringFromClass(eventClass)}];
}
+(NSString*)eventId
{
return nil;//事件優(yōu)先級
}
-(void)startEvent:(YxxAppLoginWaitWorkingModel *)model
{
NSLog(@"%@",model);
}
/**
* 清除待辦事項(xiàng)請求
*/
- (void)cancelWaitWorkingRequest:(NSString *)eventId
{
NSLog(@"%@",和服務(wù)器溝通清除事項(xiàng));
}
@end
對于子類需要實(shí)現(xiàn)四個接口
- YxxEventOne.h
@interface YxxTestWaitWorking : YxxDoWaitWorkingBaseClass
@end
- YxxEventOne.m
#import "YxxEventOne.m"
@implementation YxxTestWaitWorking
+ (void)load
{
registerWaitEvent(self, [self eventId]);
}
+ (NSString *)eventId
{
return @"eventOne";
}
- (void)startEvent:(YxxAppLoginWaitWorkingModel *)model
{
NSLog(@"%@",寫你需要做的事情,事件1);
}
@end
- YxxEventTwo.h
@interface YxxTestWaitWorking : YxxDoWaitWorkingBaseClass
@end
- YxxEventTwo.m
#import "YxxEventTwo.m"
@implementation YxxTestWaitWorking
+ (void)load
{
registerWaitEvent(self, [self eventId]);
}
+ (NSString *)eventId
{
return @"eventTwo";
}
- (void)startEvent:(YxxAppLoginWaitWorkingModel *)model
{
NSLog(@"%@",寫你需要做的事情,事件2);
}
@end
如果你看懂了上面的邏輯,那么就能夠看出,這種方式可以無限擴(kuò)張,業(yè)務(wù)的靈活性打打提升。對于我自己的模塊我不用在乎實(shí)施者的具體業(yè)務(wù),我只要求實(shí)施者的業(yè)務(wù)繼承我的父類,按照父類實(shí)現(xiàn)規(guī)定接口即可!相比v1.1版本代碼邏輯條理性有所提升,可擴(kuò)展性大幅提升,我覺得對于代碼的優(yōu)化,無非就是用最簡潔的代碼,寫出更好的邏輯。后面還有一次優(yōu)化,比現(xiàn)在的v1.2還有清晰
iOS-協(xié)議-協(xié)議的工廠設(shè)計(jì)模式-多任務(wù)需求v1.3