iOS-繼承-繼承的工廠設(shè)計(jì)模式-多任務(wù)需求v1.2-Yxx

先聲明,這篇文章并非是講什么是繼承什么是工廠模式,而是根據(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)品需求:


待辦事項(xiàng)v1.2

看圖可知,對于版本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


原創(chuàng),請忽隨意轉(zhuǎn)載
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容