一戳气、六大設(shè)計(jì)原則
- 單一職責(zé)原則:一個(gè)類只負(fù)責(zé)一件事
- 依賴倒置原則:抽象不該依賴于具體實(shí)現(xiàn)哥捕,具體實(shí)現(xiàn)可以依賴抽象
- 開閉原則:對(duì)修改關(guān)閉倒信,對(duì)擴(kuò)展開發(fā)
- 里氏替換原則:父類可以被子類無(wú)縫替換猜拾,且原有功能不受影響(例如:KVO)
- 接口隔離原則:使用多個(gè)專門的協(xié)議绍昂、而不是一個(gè)龐大臃腫的協(xié)議(例如:UITableViewDelegate,UITableViewDataSource)
- 迪米特法則:一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象盡可能少的了解(高內(nèi)聚、低耦合)
二拼岳、適配器
適配器模式(Adapter Pattern) :將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口枝誊,適配器模式使接口不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)惜纸。適配器模式既可以作為類結(jié)構(gòu)型模式侧啼,也可以作為對(duì)象結(jié)構(gòu)型模式。
本節(jié)主要學(xué)習(xí)對(duì)象適配器模式堪簿,簡(jiǎn)單的類結(jié)構(gòu)如下痊乾。
適配對(duì)象中一個(gè)成員變量指向被適配對(duì)象。
示例代碼:有兩個(gè)類Target是被適配對(duì)象椭更,CoolTarget為適配對(duì)象哪审。
Target類
#import <Foundation/Foundation.h>
@interface Target : NSObject
- (void)operation;
@end
#import "Target.h"
@implementation Target
- (void)operation
{
// 原有的具體業(yè)務(wù)邏輯
}
@end
CoolTarget類:
#import "Target.h"
// 適配對(duì)象
@interface CoolTarget : NSObject
// 被適配對(duì)象
@property (nonatomic, strong) Target *target;
// 對(duì)原有方法包裝
- (void)request;
@end
#import "CoolTarget.h"
@implementation CoolTarget
- (void)request
{
// 額外處理
[self.target operation];
// 額外處理
}
@end
適配器優(yōu)點(diǎn):
- 將目標(biāo)類和適配者類解耦,通過引入一個(gè)適配器類來(lái)重用現(xiàn)有的適配者類虑瀑,而無(wú)須修改原有代碼湿滓。
- 增加了類的透明性和復(fù)用性,將具體的實(shí)現(xiàn)封裝在適配者類中舌狗,對(duì)于客戶端類來(lái)說(shuō)是透明的叽奥,而且提高了適配者的復(fù)用性。
- 靈活性和擴(kuò)展性都非常好痛侍,通過使用配置文件朝氓,可以很方便地更換適配器,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器類,完全符合“開閉原則”赵哲。
三待德、單例
單例模式(Singleton Pattern):?jiǎn)卫J酱_保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例枫夺,這個(gè)類稱為單例類将宪,它提供全局訪問的方法。
單例模式的要點(diǎn)有三個(gè):一是某個(gè)類只能有一個(gè)實(shí)例橡庞;二是它必須自行創(chuàng)建這個(gè)實(shí)例较坛;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。單例模式是一種對(duì)象創(chuàng)建型模式扒最。單例模式又名單件模式或單態(tài)模式燎潮。
示例代碼:
@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)建實(shí)例
instance = [[super allocWithZone:NULL] init];
});
return instance;
}
// 重寫方法【必不可少】
+ (id)allocWithZone:(struct _NSZone *)zone{
return [self sharedInstance];
}
// 重寫方法【必不可少】
- (id)copyWithZone:(nullable NSZone *)zone{
return self;
}
@end
注意點(diǎn):為了防止使用者創(chuàng)建對(duì)象,需要從重寫兩個(gè)方法allocWithZone
和copyWithZone:
扼倘。另外instance = [[super allocWithZone:NULL] init];
需要使用super方法調(diào)用防止在第一創(chuàng)建時(shí)循環(huán)調(diào)用确封。
四、命令模式
命令模式(Command Pattern):將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象再菊,從而使我們可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化爪喘;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷的操作纠拔。命令模式是一種對(duì)象行為型模式秉剑,其別名為動(dòng)作(Action)模式或事務(wù)(Transaction)模式。
代碼實(shí)例:一個(gè)命令對(duì)象和一個(gè)命令管理者稠诲。
Command
@class Command;
typedef void(^CommandCompletionCallBack)(Command* cmd);
@interface Command : NSObject
@property (nonatomic, copy) CommandCompletionCallBack completion; // 執(zhí)行回調(diào)
- (void)execute; // 執(zhí)行
- (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;
// 在數(shù)組中移除
[[CommandManager sharedInstance].arrayCommands removeObject:self];
});
}
@end
CommandManager
#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
命令模式的優(yōu)點(diǎn)
- 降低系統(tǒng)的耦合度。
- 新的命令可以很容易地加入到系統(tǒng)中臀叙。
- 可以比較容易地設(shè)計(jì)一個(gè)命令隊(duì)列和宏命令(組合命令)略水。
- 可以方便地實(shí)現(xiàn)對(duì)請(qǐng)求的Undo和Redo。
代碼:DesignPatten