設(shè)計模式

一. 設(shè)計原則

  • 單一職責(zé)原則:一個類只負(fù)責(zé)一個事件:UIView只負(fù)責(zé)事件傳遞和事件相應(yīng); CALayer負(fù)責(zé)視圖展示和動畫.
  • 依賴倒置原則:抽象不應(yīng)該依賴于具體實現(xiàn), 具體實現(xiàn)可以依賴于抽象; 如上層業(yè)務(wù)調(diào)用應(yīng)依賴定義的接口(如增刪改查)
  • 開閉原則:對修改關(guān)閉, 對擴(kuò)展開放; 我們對類的定義要考慮擴(kuò)展和靈活性
  • 里氏替換原則:父類可以被子類無縫替換, 且原有功能不受任何影響; 比如KVO,當(dāng)開始監(jiān)聽A類的變量時, 就會自動生成NSKVONotify_A子類, 系統(tǒng)自動指向NSKVONotify_A , 但對外暴露的還是在操作父類, 實際上系統(tǒng)內(nèi)部是對子類的操作
  • 接口隔離原則:使用多個專門的協(xié)議, 而不是一個龐大臃腫的協(xié)議, 協(xié)議中的方法應(yīng)當(dāng)盡量少; 如UITableViewDelegate/ UITableViewDataSource
  • 迪米特法則:讓每一個對象盡量少知道其他對象都有什么, 高內(nèi)聚, 低耦合

二. 設(shè)計模式

  • 責(zé)任鏈: 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)類中的一個成員變量的類型就是這個類本身
  • 橋接
  • 適配器
  • 單利
  • 命令

1責(zé)任鏈: 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)類中的一個成員變量的類型就是這個類本身


參考


#import <Foundation/Foundation.h>

@class BusinessObject;
typedef void(^CompletionBlock)(BOOL handled);
typedef void(^ResultBlock)(BusinessObject *handler, BOOL handled);

@interface BusinessObject : NSObject

// 下一個響應(yīng)者(響應(yīng)鏈構(gòu)成的關(guān)鍵)
@property (nonatomic, strong) BusinessObject *nextBusiness;
// 響應(yīng)者的處理方法
- (void)handle:(ResultBlock)result;

// 各個業(yè)務(wù)在該方法當(dāng)中做實際業(yè)務(wù)處理
- (void)handleBusiness:(CompletionBlock)completion;
@end


#import "BusinessObject.h"

@implementation BusinessObject

// 責(zé)任鏈入口方法
- (void)handle:(ResultBlock)result
{
    CompletionBlock completion = ^(BOOL handled){
        // 當(dāng)前業(yè)務(wù)處理掉了,上拋結(jié)果
        if (handled) {
            result(self, handled);
        }
        else{
            // 沿著責(zé)任鏈,指派給下一個業(yè)務(wù)處理
            if (self.nextBusiness) {
                [self.nextBusiness handle:result];
            }
            else{
                // 沒有業(yè)務(wù)處理, 上拋
                result(nil, NO);
            }
        }
    };
    
    // 當(dāng)前業(yè)務(wù)進(jìn)行處理
    [self handleBusiness:completion];
}

- (void)handleBusiness:(CompletionBlock)completion
{
    /*
     業(yè)務(wù)邏輯處理
     如網(wǎng)絡(luò)請求、本地照片查詢等
     */
}

@end

2 橋接


#import <Foundation/Foundation.h>
#import "BaseObjectB.h"
@interface BaseObjectA : NSObject

// 橋接模式的核心實現(xiàn)
@property (nonatomic, strong) BaseObjectB *objB;

// 獲取數(shù)據(jù)
- (void)handle;

@end


#import "BaseObjectA.h"

@implementation BaseObjectA

 /*
    A1 --> B1、B2、B3         3種
    A2 --> B1、B2、B3         3種
    A3 --> B1、B2、B3         3種
  */
- (void)handle
{
    // 默認(rèn)實現(xiàn)
    [self.objB fetchData];
}

@end

#import <Foundation/Foundation.h>

@interface BaseObjectB : NSObject

- (void)fetchData;

@end

#import "BaseObjectB.h"

@implementation BaseObjectB

- (void)fetchData
{
    // override to subclass
}

@end

#import "BridgeDemo.h"

#import "BaseObjectA.h"
#import "BaseObjectB.h"

#import "ObjectA1.h"
#import "ObjectA2.h"

#import "ObjectB1.h"
#import "ObjectB2.h"

@interface BridgeDemo()
@property (nonatomic, strong) BaseObjectA *objA;
@end

@implementation BridgeDemo

/*
 根據(jù)實際業(yè)務(wù)判斷使用那套具體數(shù)據(jù)
 A1 --> B1、B2、B3         3種
 A2 --> B1、B2、B3         3種
 A3 --> B1、B2、B3         3種
 */
- (void)fetch
{
    // 創(chuàng)建一個具體的ClassA
    _objA = [[ObjectA1 alloc] init];
    
    // 創(chuàng)建一個具體的ClassB
    BaseObjectB *b1 = [[ObjectB1 alloc] init];
    // 將一個具體的ClassB1 指定給抽象的ClassB
    _objA.objB = b1;
    
    // 獲取數(shù)據(jù)
    [_objA handle];
}

@end

3 適配器模式

一個現(xiàn)有類需要適應(yīng)變化的問題?

  • 對象適配器
  • 類適配器
    - (void)request{
    //適配邏輯
    [被適配對象 某方法]
    //適配邏輯
    }
#import "Target.h"

@implementation Target

- (void)operation
{
    // 原有的具體業(yè)務(wù)邏輯
}

@end

#import "Target.h"

// 適配對象
@interface CoolTarget : NSObject

// 被適配對象
@property (nonatomic, strong) Target *target;

// 對原有方法包裝
- (void)request;

@end

#import "CoolTarget.h"

@implementation CoolTarget

- (void)request
{
    // 額外處理
    
    [self.target operation];
    
    // 額外處理
}

@end


4 單利模式[安全寫法]

#import "Mooc.h"

@implementation Mooc

+ (id)sharedInstance
{
    // 靜態(tài)局部變量
    static Mooc *instance = nil;
    
    // 通過dispatch_once方式 確保instance在多線程環(huán)境下只被創(chuàng)建一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 創(chuàng)建實例
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

// 重寫方法【必不可少】
+ (id)allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance];
}

// 重寫方法【必不可少】
- (id)copyWithZone:(nullable NSZone *)zone{
    return self;
}

@end

5命令模式

命令模式是做行為化參數(shù), 降低代碼重合度
例如: 多個新聞頁面都會有轉(zhuǎn)發(fā)/評論/贊

#import <Foundation/Foundation.h>

@class Command;
typedef void(^CommandCompletionCallBack)(Command* cmd);

@interface Command : NSObject
@property (nonatomic, copy) CommandCompletionCallBack completion;

- (void)execute;
- (void)cancel;

- (void)done;

@end

#import "Command.h"
#import "CommandManager.h"
@implementation Command

- (void)execute{
    
    //override to subclass;
    
    [self done];
}

- (void)cancel{
    
    self.completion = nil;
}

- (void)done
{
    dispatch_async(dispatch_get_main_queue(), ^{
        
        if (_completion) {
            _completion(self);
        }
        
        //釋放
        self.completion = nil;
        
        [[CommandManager sharedInstance].arrayCommands removeObject:self];
    });
}

@end

#import <Foundation/Foundation.h>
#import "Command.h"
@interface CommandManager : NSObject
// 命令管理容器
@property (nonatomic, strong) NSMutableArray <Command*> *arrayCommands;

// 命令管理者以單例方式呈現(xiàn)
+ (instancetype)sharedInstance;

// 執(zhí)行命令
+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion;

// 取消命令
+ (void)cancelCommand:(Command *)cmd;

@end

#import "CommandManager.h"

@implementation CommandManager

// 命令管理者以單例方式呈現(xiàn)
+ (instancetype)sharedInstance
{
    static CommandManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

// 【必不可少】
+ (id)allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance];
}

// 【必不可少】
- (id)copyWithZone:(nullable NSZone *)zone{
    return self;
}

// 初始化方法
- (id)init
{
    self = [super init];
    if (self) {
        // 初始化命令容器
        _arrayCommands = [NSMutableArray array];
    }
    return self;
}

+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion
{
    if (cmd) {
        // 如果命令正在執(zhí)行不做處理,否則添加并執(zhí)行命令
        if (![self _isExecutingCommand:cmd]) {
            // 添加到命令容器當(dāng)中
            [[[self sharedInstance] arrayCommands] addObject:cmd];
            // 設(shè)置命令執(zhí)行完成的回調(diào)
            cmd.completion = completion;
            //執(zhí)行命令
            [cmd execute];
        }
    }
}

// 取消命令
+ (void)cancelCommand:(Command *)cmd
{
    if (cmd) {
        // 從命令容器當(dāng)中移除
        [[[self sharedInstance] arrayCommands] removeObject:cmd];
        // 取消命令執(zhí)行
        [cmd cancel];
    }
}

// 判斷當(dāng)前命令是否正在執(zhí)行
+ (BOOL)_isExecutingCommand:(Command *)cmd
{
    if (cmd) {
        NSArray *cmds = [[self sharedInstance] arrayCommands];
        for (Command *aCmd in cmds) {
            // 當(dāng)前命令正在執(zhí)行
            if (cmd == aCmd) {
                return YES;
            }
        }
    }
    return NO;
}


@end

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

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

  • 創(chuàng)建型模式 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計模式之一。這種類型的設(shè)...
    隔墻送來秋千影閱讀 2,811評論 0 11
  • 一、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    AI喬治閱讀 1,637評論 0 2
  • 創(chuàng)建型模式 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計模式之一。這種類型的設(shè)...
    liuyang7519閱讀 388評論 0 2
  • 一、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    RamboLI閱讀 827評論 0 1
  • 設(shè)計模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗的總結(jié)。使用設(shè)...
    于先笙閱讀 583評論 1 3

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