一. 設(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




