一蛇损、觀察者模式
? ? ? 故名思意就是有一個(gè)對(duì)象在默默的看著目標(biāo)對(duì)象幕与,看它是否變化,如果變換就把變化通知給關(guān)心這個(gè)變化的對(duì)象价淌。在iOS開發(fā)中申眼,我們主要有兩種方式來實(shí)現(xiàn)觀察者模式:notification 和KVO;
? ? 1输钩、通知:notification。notification實(shí)現(xiàn)的是一對(duì)多的信息傳遞仲智,可以有多個(gè)對(duì)象收聽同一個(gè)廣播买乃,收聽廣播的對(duì)象負(fù)責(zé)回收你的廣播訂閱。
//訂閱廣播
NSNotificationCenter? * notificationCenter1 = [NSNotificationCenter? defaultCenter];? ? [notificationCenter addObserver:self? selector:@selector(update:) name:@"subjectMessage"? object:nil ];
//發(fā)生變化發(fā)出通知
[notificationCenter postNotification:subjectMessage];
//回收訂閱
[[NSNotificationCenter defaultCenter] removeObserver:self];
? 2钓辆、KVO剪验,成為鍵值觀察的機(jī)制,對(duì)象可以通過它得到其他對(duì)象特定屬性的變更通知前联,NSKeyValueObserving協(xié)議是基礎(chǔ)功戚。它和通知的區(qū)別在于,KVO是被觀察者直接向觀察者發(fā)出通知似嗤,主要用來綁定特定對(duì)象的屬性啸臀。
[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//變化后的通知內(nèi)容
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{if([keyPath isEqualToString:@"name"])? ? {NSLog(@"賦值后--%@",self.hero.name);NSLog(@"新的值--%@",change[@"new"]);NSLog(@"以前的值--%@",change[@"old"]);
}
}
[self.hero removeObserver:self forKeyPath:@"name"];//注銷觀察者。
二、delegate模式
? ? ? ?簡(jiǎn)單來說代理模式乘粒,就是把想實(shí)現(xiàn)的行為和對(duì)象分離開豌注,對(duì)象把這些行為委托給其他有能力的對(duì)象,來實(shí)現(xiàn)自己的功能灯萍。前提是轧铁,對(duì)象要把這些希望其他對(duì)象實(shí)現(xiàn)的方法,用@protocal的形式聲明出來旦棉。所有接受委托的的對(duì)象齿风,也要明確的接受這個(gè)協(xié)議才可以。最常見的就是tableView的delegate和dataSource绑洛。這個(gè)太多救斑,掠過細(xì)節(jié)。
三诊笤、MVC模式
? ? ? ?根據(jù)功能把a(bǔ)pp中的類分為Model系谐、View、Controller三個(gè)角色讨跟,這是iOS開發(fā)的經(jīng)典模式纪他;
模型會(huì)把任何數(shù)據(jù)的變更通知控制器,然后控制器更新視圖數(shù)據(jù)晾匠。視圖對(duì)象通知控制器用戶的操作茶袒,控制器要么根據(jù)需要來更新模型,要么檢索任何被請(qǐng)求的數(shù)據(jù)凉馆。
你可能在想為什么不能僅僅使用控制器薪寓,在一個(gè)類中實(shí)現(xiàn)視圖和模型,這樣貌似更加容易澜共?
所有的這些都?xì)w結(jié)于代碼關(guān)注點(diǎn)分離以及復(fù)用向叉。在理想的狀態(tài)下,視圖應(yīng)該和模型完全的分離嗦董。如果視圖不依賴某個(gè)實(shí)際的模型母谎,那么視圖就可以被復(fù)用來展示不同模型的數(shù)據(jù)。
四京革、MVVM模式
五奇唤、單利模式
? ? ? ? 單例設(shè)計(jì)模式確保對(duì)于一個(gè)給定的類只有一個(gè)實(shí)例存在,這個(gè)實(shí)例有一個(gè)全局唯一的訪問點(diǎn)匹摇。它通常采用懶加載的方式在第一次用到實(shí)例的時(shí)候再去創(chuàng)建它咬扇。
? ? ? ? 例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],這是Apple系統(tǒng)給我提供的單例廊勃。我們也可以自己創(chuàng)建單例懈贺,比如視頻播放器、比如賬號(hào)對(duì)象、等等隅居。
? ? ? ?單例的要點(diǎn):1钠至、該類有且只有一個(gè)實(shí)例;2胎源、該類必須能夠自行創(chuàng)建實(shí)例棉钧;3、該類可以向整個(gè)系統(tǒng)提供這個(gè)實(shí)例涕蚤。
? ? ? ?單例的優(yōu)點(diǎn):提供了唯一對(duì)象宪卿,在內(nèi)存中只有一個(gè)對(duì)象節(jié)約資源,提高性能万栅。更靈活的實(shí)例化過程佑钾。
? ? ? ?單例的缺點(diǎn):?jiǎn)卫龥]有抽象層,擴(kuò)展很困難烦粒。單例職責(zé)過重休溶,違背了單一職責(zé)原則。
單例的實(shí)現(xiàn)如下:
@implementation ?Singleton
static Singleton * sharedSingleton =nil;
+ (Singleton *) sharedInstance
{if(sharedSingleton ==nil) {
sharedSingleton=[[Singleton alloc] init];
}
return sharedSingleton;
}
@end
另外有一個(gè)GCD的單例方式:
static Myclass _instance;
方法一:
+(id)shareInstance{
@synchronized(self){
if(_instance == nil)
_instance = [MyClass alloc] init];
}
return _instance;
}
方法二:
+(id)shareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(_instance == nil)
_instance = [MyClass alloc] init];
});
return _instance;
}
//重寫allocWithZone,里面實(shí)現(xiàn)跟方法一,方法二一致就行.
+(id)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(_instance == nil)
_instance = [MyClass alloc] init];
});
return _instance;
} 這個(gè)函數(shù)重寫扰她,否則是錯(cuò)誤的兽掰。請(qǐng)讀者注意。
//保證copy時(shí)相同
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
單例需要注意的是在ARC和MRC下寫法有所不同
MRC下創(chuàng)建單例步驟一樣徒役,不過要處理一些內(nèi)存管理的函數(shù)
-(id)retain{//計(jì)數(shù)器不用加1
return self ;
}
-(id)autorelease{//不需要孽尽,堆區(qū)對(duì)象才需要
return self;
}
-(oneway void)release{};
-(NSUInteger)retainCount{return UINT_MAX;}
單例的銷毀:
在mrc下
+(void)attemptDealloc{
[_instance release]; //mrc 需要釋放,當(dāng)然你就不能重寫release的方法了.
_instance = nil;
}
必須把static dispatch_once_t onceToken; 這個(gè)拿到函數(shù)體外,成為全局的
+(void)attempDealloc{
onceToken = 0; // 只有置成0,GCD才會(huì)認(rèn)為它從未執(zhí)行過.它默認(rèn)為0.這樣才能保證下次再次調(diào)用shareInstance的時(shí)候,再次創(chuàng)建對(duì)象.
[_instance release];
_instance = nil;
}
六、策略模式 Policy
? ? ? ?一系列的算法,把每一個(gè)算法封裝起來, 并且使它們可相互替換忧勿。本模式使得算法可獨(dú)立于使用它的客戶而變化杉女。
? ? ? ? 我們?cè)隍?yàn)證用戶輸入的表單的時(shí)候,加入包括電話輸入框的驗(yàn)證和郵件輸入框的驗(yàn)證鸳吸,這兩部分的驗(yàn)證算法是不同的熏挎,如果把這個(gè)算法看成一個(gè)函數(shù),他幾乎有相同的輸入?yún)?shù)和返回參數(shù)晌砾。我們可以把這個(gè)相同的函數(shù)可以抽象為基類(InputValidator)的一個(gè)方法(bool validateInput(input,error))坎拐,然后抽象出兩個(gè)具體的策略類:電話驗(yàn)證類(PhoneValidator)和郵件驗(yàn)證類(EmailValidator),他們需要在各自的實(shí)現(xiàn)里面去復(fù)寫父類的驗(yàn)證方法贡羔。為了能夠正常的調(diào)用到驗(yàn)證類的驗(yàn)證方法廉白,我們需要自定義一個(gè)UITextField的子類CustomTextField个初,其中有一個(gè)InputValidator類型的引用和一個(gè)validate方法乖寒,該方法里面調(diào)用InputValidator的驗(yàn)證方法,然后在textFieldDidEndEditing代理方法里面調(diào)用CustomTextField的validate方法院溺,這樣就不用我們?cè)谂袛噍斎胧欠窈戏ǖ臅r(shí)候通過if else去處理每種邏輯楣嘁,而且這樣做方便擴(kuò)展,提高可復(fù)用性
七、工廠模式
就是類方法逐虚,創(chuàng)建對(duì)象更方便一些聋溜。
八、MVVM
? ? ? ? 隨著現(xiàn)在App的功能的增加導(dǎo)致復(fù)雜程度的提高叭爱,我們?cè)赩iew Controller放的東西越來越多撮躁,許多邏輯被放在 View Controller 里。它們中的一些確實(shí)屬于 View Controller买雾,但更多的是所謂的“表示邏輯(presentation logic)”把曼,就是那些將 Model 數(shù)據(jù)轉(zhuǎn)換為 View 可以呈現(xiàn)的東西的事情。
? ? ? MVVM的引進(jìn)漓穿,不是用ViewModel來取代View Controller嗤军,而是把“表示邏輯”從View Controller中抽出來放到ViewModel中,來緩解View Controller的壓力晃危,MVVM 聽起來很復(fù)雜叙赚,但它本質(zhì)上就是一個(gè)精心優(yōu)化的 MVC 架構(gòu),而 MVC 你早已熟悉僚饭。
? ? ? 在 iOS 上使用 MVVM 的動(dòng)機(jī)震叮,對(duì)我來說,無論如何浪慌,就是它能減少 View Controller 的復(fù)雜性并使得表示邏輯更易于測(cè)試冤荆。