iOS中都有什么设计模式?各个设计模式的作用 (转载)
原文地址: http://www.cnblogs.com/dxb123456/p/5479198.html
一 ?iOS中都有什么設(shè)計(jì)模式?
1.代理模式
2.觀察者模式
3.MVC模式
4.單例模式
5.策略模式
6.工廠模式
?
二 ?各個(gè)設(shè)計(jì)模式的作用?
(一)代理模式
在觀察者模式中,一個(gè)對(duì)象任何狀態(tài)的變更都會(huì)通知另外的對(duì)改變感興趣的對(duì)象。這些對(duì)象之間不需要知道彼此的存在,這其實(shí)是一種松耦合的設(shè)計(jì)。當(dāng)某個(gè)屬性變化的時(shí)候,我們通常使用這個(gè)模式去通知其它對(duì)象。
此模式的通用實(shí)現(xiàn)中,觀察者注冊(cè)自己感興趣的其它對(duì)象的狀態(tài)變更事件。當(dāng)狀態(tài)發(fā)生變化的時(shí)候,所有的觀察者都會(huì)得到通知。蘋(píng)果的推送通知(Push Notification)就是一個(gè)此模式的例子。
如果你要遵從MVC模式的概念,你需要讓模型對(duì)象和視圖對(duì)象在不相互直接引用的情況下通信。這正是觀察者模式的用武之地。
?
Cocoa通過(guò)通知(Notifications)和Key-Value Observing(KVO)來(lái)實(shí)現(xiàn)觀察者模式。
?
在cocoa框架中的Delegate模式中,委托人往往是框架中的對(duì)象(視圖中的控件、表視圖神馬的),代理人往往是視圖控制器對(duì)象。
在我們這個(gè)例子中UITableView是委托人,代理人首先得滿(mǎn)足一個(gè)條件:就是在.h文件中申明它擁有代理資格:
@interface WhateverViewController < UITableViewDelegate > @end紅色的表示這個(gè)視圖控制器擁有UITableView的代理資格。
其次,在.m文件中定義委托人可以讓代理人去代替做的事情:
//視圖控制器來(lái)代辦應(yīng)該有多少個(gè)節(jié) - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return [NSArray count]; }//視圖控制器來(lái)代辦某個(gè)節(jié)應(yīng)該有多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return [[NSArray objectAtIndex:section]count]; } // 視圖控制器來(lái)代辦負(fù)責(zé)每個(gè)欄格的外觀 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *CellIdentifier = @"Cell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) {cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];}cell.textField.text = [NSArray objectAtIndex:indexPath.row]; return cell; } //負(fù)責(zé)當(dāng)欄格被點(diǎn)擊后需要觸發(fā)的事件 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {AnotherViewController *anotherViewController = [[AnotherViewController alloc]initWithNibName:@"AnotherView" bundle:nil];[self.navigationController pushViewController:anotherViewController];[anotherViewController release]; } // 這個(gè)是可選的,視圖控制器勤快我就幫你代辦,不勤快我就可以不幫你辦這事兒,(提供哪些個(gè)行可以被編輯) - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {return YES; }
// 對(duì)特定編輯風(fēng)格進(jìn)行操作 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];}else if (editingStyle == UITableViewCellEditingStyleInsert) {} }
// 可選,對(duì)那些被移動(dòng)欄格作特定操作 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { }
// 對(duì)那些可以移動(dòng)的行返回YES - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {// 如果不想讓欄格移動(dòng),就返回NOreturn YES; }
?好了,當(dāng)這個(gè)委托人需要辦這些事時(shí),代理人自己就站出來(lái)幫忙辦了。這就是ios中的Delegate模式。
二、自定義的delegate模式
@interface A:UIView id transparendValueDelegate; @property(nomatic, retain) id transparendValueDelegate;@end@implementation A @synthesize transparendValueDelegate-(void)Call { NSString* value = @"你好"; [transparendValueDelegate transparendValue: value]; }@end@interface B:UIView NSString* value; @end
@implementation B -(void)transparendValue:(NSString*)fromValue { value = fromValue; NSLog(@"%@ ,我是B",value); } @end
使用時(shí):
A* a = [[A alloc] init]; B* b = [[B alloc] init]; a. transparendValueDelegate = b;//設(shè)置A代理委托對(duì)象為B [a Call];這樣就會(huì)輸出:
你好,我是B
?委托模式關(guān)鍵就在于一個(gè)“被”字。這個(gè)B是很被動(dòng)的,隨時(shí)就會(huì)被你A Call一下。
?
三、為什么會(huì)有delegate模式
換句話(huà)說(shuō),它可以用來(lái)解決神馬問(wèn)題?
當(dāng)一個(gè)類(lèi)的某些功能需要被別人來(lái)實(shí)現(xiàn),但是既不明確是些什么功能,又不明確誰(shuí)來(lái)實(shí)現(xiàn)這些功能的時(shí)候,委托模式就可以派上用場(chǎng)。
例如你可以再寫(xiě)個(gè)C類(lèi),實(shí)現(xiàn)-(void)transparendValue:(NSString*)fromValue {NSLog(@"%@ ,我是C",value); }也是完全可以的。換誰(shuí)來(lái),只要它實(shí)現(xiàn)了這個(gè)方法,我就可以委托它來(lái)做這個(gè)事。
說(shuō)到底一切都是為了使類(lèi)之間的耦合性更松散。好的代碼應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。
?
總結(jié)來(lái)自http://blog.sina.com.cn/s/blog_b638dc89010192qu.html
(二)觀察者模式
在軟件開(kāi)發(fā)中,無(wú)論是那種高級(jí)語(yǔ)言中總會(huì)伴隨著一些最為常用的設(shè)計(jì)模式,即便就如iOS開(kāi)發(fā)中與我們打交道最多的無(wú)非就是單例模式、觀察者模式和工廠模式了,當(dāng)然了其他的設(shè)置模式也同樣存在在編程的很多地方。下面就就讓我們簡(jiǎn)單的了解下觀察者模式吧!
觀察者模式本質(zhì)上時(shí)一種發(fā)布-訂閱模型,用以消除具有不同行為的對(duì)象之間的耦合,通過(guò)這一模式,不同對(duì)象可以協(xié)同工作,同時(shí)它們也可以被復(fù)用于其他地方Observer從Subject訂閱通知,ConcreteObserver實(shí)現(xiàn)重現(xiàn)ObServer并將其重載其update方法。一旦SubJect的實(shí)例需要通知Observer任何新的變更,Subject會(huì)發(fā)送update消息來(lái)通知存儲(chǔ)在其內(nèi)部類(lèi)中所注冊(cè)的Observer、在ConcreteObserver的update方法的實(shí)際實(shí)現(xiàn)中,Subject的內(nèi)部狀態(tài)可被取得并進(jìn)行后續(xù)處理。其類(lèi)圖如下:
?
觀察者模式.png
由上面我們可以發(fā)現(xiàn)觀察者模式無(wú)非在是定義對(duì)象間的一種一對(duì)多的依賴(lài)關(guān)系,并且當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變的時(shí)候,所有依賴(lài)于它的對(duì)象都會(huì)得到通知且自動(dòng)更新。即如果Subject允許其他觀察者(實(shí)現(xiàn)了觀察者接口的對(duì)象)對(duì)這個(gè)Subject的改變進(jìn)行請(qǐng)閱,當(dāng)Subject發(fā)送了變化,那么Subject會(huì)將這個(gè)變化發(fā)送給所有的觀察者,觀察者就能對(duì)Subject的變化做出更新。其時(shí)序圖如下
?
觀察者模式2.png
通過(guò)上面的觀察我們可以發(fā)現(xiàn)如果用N個(gè)Observer來(lái)拓展Subject的行為,這些Observer具有處理存儲(chǔ)在Subject中的信息的特定實(shí)現(xiàn),這樣也就實(shí)現(xiàn)了前面所說(shuō)的消除不同對(duì)象間的耦合的功能了。
那么了解了這些我們可能就會(huì)更像了解下我們?cè)谑裁磿r(shí)候才會(huì)去使用觀察者模式呢?
- 當(dāng)需要將改變通知所有的對(duì)象時(shí),而你又不知道這些對(duì)象的具體類(lèi)型
- 改變發(fā)生在同一個(gè)對(duì)象中,并需要改變其他對(duì)象將相關(guān)的狀態(tài)進(jìn)行更新且不知道有多少個(gè)對(duì)象。
而同樣的在我們?nèi)粘5拈_(kāi)發(fā)中在Cocoa Touch框架中的的兩種經(jīng)常打交道的技術(shù)KVO與通知都實(shí)現(xiàn)了觀察者模式,所以下面我們討論的重點(diǎn)也就是基于這兩個(gè)方面的。
通知
在之前的博文中曾經(jīng)簡(jiǎn)單的提到過(guò)一些通知的基礎(chǔ)使用方法,所以一些基本的使用方法再次就不贅述。言歸正傳,在Cocoa Touch框架中NSNotificationCenter和NSNotification對(duì)象實(shí)現(xiàn)了一對(duì)多的模型。通過(guò)NSNotificationCenter可以讓對(duì)象之間進(jìn)行通訊,即便這些對(duì)象之間并不認(rèn)識(shí)。下面我們來(lái)看下NSNotificationCenter發(fā)布消息的方法:
NSNotification * subjectMessage = [ NSNotification notificationWithName:@"subjectMessage" object: self];NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter]; [notificationCenter postNotification:subjectMessage];通過(guò)上面的代碼我們創(chuàng)建了一個(gè)名為subjectMessage的NSNotification對(duì)象,然后通過(guò)notificationCenter來(lái)發(fā)布這個(gè)消息。通過(guò)向NSNotificationCenter類(lèi)發(fā)送defaulCenter消息,可以得到NSNotificationCenter實(shí)例的引用。每個(gè)進(jìn)程中只有一個(gè)默認(rèn)的通知中心,所以默認(rèn)的NSNotificationCenter是個(gè)單例對(duì)象。如果有其他觀察者定于了其對(duì)象的相關(guān)事件則可以通過(guò)以下的方法來(lái)進(jìn)行操作:
NSNotificationCenter * notificationCenter1 = [ NSNotificationCenter defaultCenter];[notificationCenter addObserver: self selector: @selector(update:) name:@"subjectMessage" object: nil ];經(jīng)過(guò)以上步驟我們已經(jīng)向通知中心注冊(cè)了一個(gè)事件并且通過(guò)selector制定了一個(gè)方法update:下面我們可以實(shí)現(xiàn)以下這個(gè)方法
- (void)update:(NSNotification*)notification{if ([[notification name] isEqualToString:@"subjectMessage"]) {NSLog(@"%@",@"猴子派來(lái)的救兵去哪了?"); } }當(dāng)然最后如果我們需要對(duì)監(jiān)聽(tīng)進(jìn)行銷(xiāo)毀
- (void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self]; }了解過(guò)通知之后我們來(lái)看一下KVO
KVO是Cocoa提供的一種稱(chēng)為鍵值觀察的機(jī)制,對(duì)象可以通過(guò)它得到其他對(duì)象特定屬性的變更通知。而這個(gè)機(jī)制是基于NSKeyValueObserving非正式些,Cocoa通過(guò)這個(gè)協(xié)議為所有遵循協(xié)議的對(duì)象提供了一種自動(dòng)化的屬性監(jiān)聽(tīng)的功能。
雖然通知和KVO都可以對(duì)觀察者進(jìn)行實(shí)現(xiàn),但是他們之間還是略有不同的,由上面的例子我們可以看出通知是由一個(gè)中心對(duì)象為所有觀察者提供變更通知,主要是廣義上關(guān)注程序事件,而KVO則是被觀察的對(duì)象直接想觀察者發(fā)送通知,主要是綁定于特定對(duì)象屬性的值。下面我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)了解下他的一些是使用方法
首先我們有Hero這個(gè)模型
@property (nonatomic,copy) NSString * name; @property (nonatomic,copy) NSString * title; @property (nonatomic,assign) NSUInteger age;在控制其中我們將其初始化并賦值
self.hero = [[Hero alloc] init];self.hero.name = @"趙云"; self.hero.title = @"將軍"; self.hero.age = 87;現(xiàn)在我們的這個(gè)對(duì)象基本有值了,那么我們將這個(gè)對(duì)象的name監(jiān)聽(tīng)下他的改變
[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];觸發(fā)通知并將值改變
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{self.hero.name = @"張飛"; }在制定的回調(diào)函數(shù)中,處理收到的更改通知
- (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"]); } }回調(diào)打印如下:
?
dayin.png
最后注銷(xiāo)觀察者
- (void)dealloc{[self.hero removeObserver:self forKeyPath:@"name"]; }到了這里觀察者模式中常用的KVO及通知的內(nèi)容就到這里,不過(guò)要知道這里談及的只是最基礎(chǔ)的用法,后面我們可能還是有更加深入的探究,或者在后續(xù)中可能還會(huì)對(duì)比iOS中的代理以及Block來(lái)探尋下iOS中的消息傳遞機(jī)制,再或者像Swift中的didSet、willSet的屬性監(jiān)聽(tīng)的方法,這些都是很好玩的內(nèi)容,不是么?
(三)MVC模式
MVC根據(jù)角色劃分類(lèi),涉及到三個(gè)角色:
Model:模型保存應(yīng)用程序的數(shù)據(jù)。
View:視圖是模型的可視化表示以及用戶(hù)交互的控件。
Controller:控制器是一個(gè)協(xié)調(diào)所有工作的中介者。它訪(fǎng)問(wèn)模型中的數(shù)據(jù)并在視圖中展示它們,同時(shí)它們還監(jiān)聽(tīng)事件和操作數(shù)據(jù)。
一個(gè)MVC模式的好的實(shí)現(xiàn)也就意味著每一個(gè)對(duì)象都會(huì)被劃分到上面所說(shuō)的組中。
我們可以很好的用下圖來(lái)描述通過(guò)控制器實(shí)現(xiàn)的視圖到模型的交互過(guò)程:
模型會(huì)把任何數(shù)據(jù)的變更通知控制器,然后控制器更新視圖數(shù)據(jù)。視圖對(duì)象通知控制器用戶(hù)的操作,控制器要么根據(jù)需要來(lái)更新模型,要么檢索任何被請(qǐng)求的數(shù)據(jù)。
你可能在想為什么不能僅僅使用控制器,在一個(gè)類(lèi)中實(shí)現(xiàn)視圖和模型,這樣貌似更加容易?
所有的這些都?xì)w結(jié)于代碼關(guān)注點(diǎn)分離以及復(fù)用。在理想的狀態(tài)下,視圖應(yīng)該和模型完全的分離。如果視圖不依賴(lài)某個(gè)實(shí)際的模型,那么視圖就可以被復(fù)用來(lái)展示不同模型的數(shù)據(jù)。
舉個(gè)例子來(lái)說(shuō),如果將來(lái)你打算加入電影或者書(shū)籍到你的資料庫(kù)中,你仍然可以使用同樣的AlbumView去顯示電影和書(shū)籍?dāng)?shù)據(jù)。更進(jìn)一步來(lái)說(shuō),如果你想創(chuàng)建一個(gè)新的與專(zhuān)輯有關(guān)聯(lián)的工程,你可以很簡(jiǎn)單的復(fù)用Album類(lèi),因?yàn)樗灰蕾?lài)任何視圖。這就是MVC的強(qiáng)大之處。
?
(四)單例模式
單例設(shè)計(jì)模式確保對(duì)于一個(gè)給定的類(lèi)只有一個(gè)實(shí)例存在,這個(gè)實(shí)例有一個(gè)全局唯一的訪(fǎng)問(wèn)點(diǎn)。它通常采用懶加載的方式在第一次用到實(shí)例的時(shí)候再去創(chuàng)建它。
?
注意:蘋(píng)果大量使用了此模式。例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],所有的這些方法都返回一個(gè)單例對(duì)象。
?
你很可能會(huì)想為什么這么關(guān)心是否一個(gè)類(lèi)有多個(gè)實(shí)例?畢竟代碼和內(nèi)存都是廉價(jià)的,對(duì)嗎??
有一些情況下,只有一個(gè)實(shí)例顯得非常合理。舉例來(lái)說(shuō),你不需要有多個(gè)Logger的實(shí)例,除非你想去寫(xiě)多個(gè)日志文件。或者一個(gè)全局的配置處理類(lèi):實(shí)現(xiàn)線(xiàn)程安全的方式訪(fǎng)問(wèn)共享實(shí)例是容易的,比如一個(gè)配置文件,有好多個(gè)類(lèi)同時(shí)修改這個(gè)文件。
?
(五)策略模式
1.概述
在軟件開(kāi)發(fā)中也常常遇到類(lèi)似的情況,實(shí)現(xiàn)某一個(gè)功能有多種算法或者?策略,我們可以根據(jù)環(huán)境或者條件的不同選擇不同的算法或者策略來(lái)完成該功能?。如查找、排序等,一種常用的方法是硬編碼(Hard Coding)在一個(gè)類(lèi)中,如需要提供多種查找算法,可以將這些算法寫(xiě)到一個(gè)類(lèi)中,在該類(lèi)中提供多個(gè)方法,每一個(gè)方法對(duì)應(yīng)一個(gè)具體的查找算法;當(dāng)然也可以將這些查找算法封裝在一個(gè)統(tǒng)一的方法中,通過(guò)if…else…或者?case?等條件判斷語(yǔ)句來(lái)進(jìn)行選擇。這兩種實(shí)現(xiàn)方法我們都可以稱(chēng)之為硬編碼,如果需要增加一種新的查找算法,需要修改封裝算法類(lèi)的源代碼;更換查找算法,也需要修改客戶(hù)端調(diào)用代碼。在這個(gè)算法類(lèi)中封裝了大量查找算法,?該類(lèi)代碼將較復(fù)雜,維護(hù)較為困難。如果我們將這些策略包含在客戶(hù)端?,這種做法更不可取,將導(dǎo)致客戶(hù)端程序龐大而且難以維護(hù),如果存在大量可供選擇的算法時(shí)問(wèn)題將變得更加嚴(yán)重。
例子1:一個(gè)菜單功能能夠根據(jù)用戶(hù)的“皮膚”首選項(xiàng)來(lái)決定是否采用水平的還是垂直的排列形式。同事可以靈活增加菜單那的顯示樣式。
例子2:出行旅游:我們?可以有幾個(gè)策略可以考慮:可以騎自行車(chē),汽車(chē),做火車(chē),飛機(jī)。每個(gè)策略都可以得到相同的結(jié)果,但是它們使用了不同的資源。選擇策略的依據(jù)是費(fèi)用,時(shí)間,使用工具還有每種方式的方便程度 。
2.問(wèn)題
?
如何讓算法和對(duì)象分開(kāi)來(lái),使得算法可以獨(dú)立于使用它的客戶(hù)而變化??
3.解決方案
策略模式:?定?義一系列的算法,把每一個(gè)算法封裝起來(lái), 并且使它們可相互替換。本模式使得算法可獨(dú)立于使用它的客戶(hù)而變化。?也稱(chēng)為?政策模式?(Policy)?。(?Definea family of algorithms,encapsulate each one, andmake them interchangeable. Strategy lets the algorithmvary independently from clients that use it.??)
策略模式把對(duì)象本身和運(yùn)算規(guī)則區(qū)分開(kāi)來(lái),其?功能非常強(qiáng)大,因?yàn)檫@個(gè)設(shè)計(jì)模式本身的核心思想就是面向?qū)ο缶幊痰亩嘈涡缘乃枷搿?/p>
4.適用性
?
當(dāng)存在以下情況時(shí)使用Strategy模式
1)? 許多相關(guān)的類(lèi)僅僅是行為有異。 “策略”提供了一種用多個(gè)行為中的一個(gè)行為來(lái)配置一個(gè)類(lèi)的方法。即一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。
2)? 需要使用一個(gè)算法的不同變體。例如,你可能會(huì)定義一些反映不同的空間 /時(shí)間權(quán)衡的算法。當(dāng)這些變體實(shí)現(xiàn)為一個(gè)算法的類(lèi)層次時(shí) ,可以使用策略模式。
3)? 算法使用客戶(hù)不應(yīng)該知道的數(shù)據(jù)。可使用策略模式以避免暴露復(fù)雜的、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)。
4)? 一個(gè)類(lèi)定義了多種行為 , 并且這些行為在這個(gè)類(lèi)的操作中以多個(gè)條件語(yǔ)句的形式出現(xiàn)。將相關(guān)的條件分支移入它們各自的Strategy類(lèi)中以代替這些條件語(yǔ)句。
?
5.結(jié)構(gòu)
6.效果
Strategy模式有下面的一些優(yōu)點(diǎn):
?
1) 相關(guān)算法系列?
Strategy類(lèi)層次為Context定義了一系列的可供重用的算法或行為。?繼承有助于析取出這些算法中的公共功能。??
2) 提供了可以替換繼承關(guān)系的辦法
: 繼承提供了另一種支持多種算法或行為的方法。你可以直接生成一個(gè)Context類(lèi)的子類(lèi),從而給它以不同的行為。但這會(huì)將行為硬行編制到 Context中,而將算法的實(shí)現(xiàn)與Context的實(shí)現(xiàn)混合起來(lái),從而使Context難以理解、難以維護(hù)和難以擴(kuò)展,而且還不能動(dòng)態(tài)地改變算法。最后你得到一堆相關(guān)的類(lèi) , 它們之間的唯一差別是它們所使用的算法或行為。?將算法封裝在獨(dú)立的Strategy類(lèi)中使得你可以獨(dú)立于其Context改變它,使它易于切換、易于理解、易于擴(kuò)展。??
3) 消除了一些if else條件語(yǔ)句
:Strategy模式提供了用條件語(yǔ)句選擇所需的行為以外的另一種選擇。當(dāng)不同的行為堆砌在一個(gè)類(lèi)中時(shí) ,很難避免使用條件語(yǔ)句來(lái)選擇合適的行為。將行為封裝在一個(gè)個(gè)獨(dú)立的Strategy類(lèi)中消除了這些條件語(yǔ)句。含有許多條件語(yǔ)句的代碼通常意味著需要使用Strategy模式。?4) 實(shí)現(xiàn)的選擇
Strategy模式可以提供相同行為的不同實(shí)現(xiàn)。客戶(hù)可以根據(jù)不同時(shí)間 /空間權(quán)衡取舍要求從不同策略中進(jìn)行選擇。
Strategy模式缺點(diǎn)?:?
?
1)客戶(hù)端必須知道所有的策略類(lèi),并自行決定使用哪一個(gè)策略類(lèi)
: ?本模式有一個(gè)潛在的缺點(diǎn),就是一個(gè)客戶(hù)要選擇一個(gè)合適的Strategy就必須知道這些Strategy到底有何不同。此時(shí)可能不得不向客戶(hù)暴露具體的實(shí)現(xiàn)問(wèn)題。因此僅當(dāng)這些不同行為變體與客戶(hù)相關(guān)的行為時(shí) , 才需要使用Strategy模式。??
2 ) Strategy和Context之間的通信開(kāi)銷(xiāo)
:無(wú)論各個(gè)ConcreteStrategy實(shí)現(xiàn)的算法是簡(jiǎn)單還是復(fù)雜, 它們都共享Strategy定義的接口。因此很可能某些 ConcreteStrategy不會(huì)都用到所有通過(guò)這個(gè)接口傳遞給它們的信息;簡(jiǎn)單的 ConcreteStrategy可能不使用其中的任何信息!這就意味著有時(shí)Context會(huì)創(chuàng)建和初始化一些永遠(yuǎn)不會(huì)用到的參數(shù)。如果存在這樣問(wèn)題 , 那么將需要在Strategy和Context之間更進(jìn)行緊密的耦合。?3 )策略模式將造成產(chǎn)生很多策略類(lèi)
:可以通過(guò)使用享元模式在一定程度上減少對(duì)象的數(shù)量。 增加了對(duì)象的數(shù)目 Strategy增加了一個(gè)應(yīng)用中的對(duì)象的數(shù)目。有時(shí)你可以將 Strategy實(shí)現(xiàn)為可供各Context共享的無(wú)狀態(tài)的對(duì)象來(lái)減少這一開(kāi)銷(xiāo)。任何其余的狀態(tài)都由 Context維護(hù)。Context在每一次對(duì)Strategy對(duì)象的請(qǐng)求中都將這個(gè)狀態(tài)傳遞過(guò)去。共享的 Strategy不應(yīng)在各次調(diào)用之間維護(hù)狀態(tài)。
7. iOS應(yīng)用分析
例如,我們?cè)隍?yàn)證用戶(hù)輸入的表單的時(shí)候,加入包括電話(huà)輸入框的驗(yàn)證和郵件輸入框的驗(yàn)證,這兩部分的驗(yàn)證算法是不同的,如果把這個(gè)算法看成一個(gè)函數(shù),他幾乎有相同的輸入?yún)?shù)和返回參數(shù)。我們可以把這個(gè)相同的函數(shù)可以抽象為基類(lèi)(InputValidator)的一個(gè)方法(bool validateInput(input,error)),然后抽象出兩個(gè)具體的策略類(lèi):電話(huà)驗(yàn)證類(lèi)(PhoneValidator)和郵件驗(yàn)證類(lèi)(EmailValidator),他們需要在各自的實(shí)現(xiàn)里面去復(fù)寫(xiě)父類(lèi)的驗(yàn)證方法。為了能夠正常的調(diào)用到驗(yàn)證類(lèi)的驗(yàn)證方法,我們需要自定義一個(gè)UITextField的子類(lèi)CustomTextField,其中有一個(gè)InputValidator類(lèi)型的引用和一個(gè)validate方法,該方法里面調(diào)用InputValidator的驗(yàn)證方法,然后在textFieldDidEndEditing代理方法里面調(diào)用CustomTextField的validate方法,這樣就不用我們?cè)谂袛噍斎胧欠窈戏ǖ臅r(shí)候通過(guò)if else去處理每種邏輯,而且這樣做方便擴(kuò)展,提高可復(fù)用性。?
實(shí)例:排序算法,NSArray的sortedArrayUsingSelector;經(jīng)典的鴨子會(huì)叫,會(huì)飛案例。??
(六)工廠模式
工廠模式我的理解是:他就是為了創(chuàng)建對(duì)象的
創(chuàng)建對(duì)象的時(shí)候,我們一般是alloc一個(gè)對(duì)象,如果需要?jiǎng)?chuàng)建100個(gè)這樣的對(duì)象,如果是在一個(gè)for循環(huán)中還好說(shuō),直接一句alloc就行了,但是事實(shí)并不那么如意,我們可能會(huì)在不同的地方去創(chuàng)建這個(gè)對(duì)象,那么我們可能需要寫(xiě)100句alloc 了,但是如果我們?cè)趧?chuàng)建對(duì)象的時(shí)候,需要在這些對(duì)象創(chuàng)建完之后,為它的一個(gè)屬性添加一個(gè)固定的值,比方說(shuō)都是某某學(xué)校的學(xué)生,那么可能有需要多些100行重復(fù)的代碼了,那么,如果寫(xiě)一個(gè)-(void)createObj方法,把創(chuàng)建對(duì)象和學(xué)校屬性寫(xiě)在這個(gè)方法里邊,那么就是會(huì)省事很多,也就是說(shuō)我們可以alloc 創(chuàng)建對(duì)象封裝到一個(gè)方法里邊,直接調(diào)用這個(gè)方法就可以了,這就是簡(jiǎn)單工廠方法
代碼結(jié)構(gòu)如下
Animal 類(lèi)
@interface Animal :NSObject
@proterty(nonatomic,strong) NSString *name;
-(void)laugh;
@end
Dog類(lèi)
?
@interface Dog:Animal
@end
?
Cat類(lèi)
@interface?Cat:Animal
@end
?
創(chuàng)建對(duì)象的工廠類(lèi)
.h
@interface?AnimalFactory:NSObject
+(Dog *)createDog;
+(Cat *)createCat;
@end
.m
@implementation AnimalFactory
+(Dog?*)createDog{
????Dog *dog=[[Dog alloc]init];
? ? dog.name=@“baby”;
????return dog;
}
?
+(Cat?*)?createCat{
? ??Cat?*cat=[[Cat?alloc]init];
????return cat;
}
Main.m文件
Dog *dog=[AnimalFactory createDog];
Cat *cat=[AnimalFactory createCat];
這是簡(jiǎn)單工廠模式
現(xiàn)在創(chuàng)建100個(gè)Dog對(duì)象,如果這100個(gè)對(duì)象寫(xiě)在程序中的不同地方,按上邊的方法是需要把Dog *dog=[AnimalFactory createDog];這一句話(huà)寫(xiě)在程序中很多不同的地方,那么現(xiàn)在有一個(gè)需求,就是如果需要把這些創(chuàng)建的100個(gè)Dog對(duì)象全部變成Cat對(duì)象,那么按照剛才的那個(gè)做法,就需要在這100句代碼中把createDog方法變成createCat方法了,這樣做還是很復(fù)雜
那么這個(gè)時(shí)候用工廠方法模式就能解決這個(gè)難題了
工廠方法模式是為每一個(gè)要?jiǎng)?chuàng)建的對(duì)象所在的類(lèi)都相應(yīng)地創(chuàng)建一個(gè)工廠
代碼如下
@interface?AnimalFactory:NSObject
-(Animal*)createAnimal;
@end;
Dog工廠類(lèi)
@interface DogFactory:AnimalFactory;
@implementation DogFactory
-(Animal *)createAnimal{
retrurn [[Dog alloc]init];
}
@end
Cat工廠類(lèi)
@interface?CatFactory:AnimalFactory;
@implementation?Cat?Factory
-(Animal *)createAnimal
retrurn [[Cat?alloc]init];
}
@end
Main.m
AnimalFactory *dogFactory=[[DogFactory alloc]init];
?
Animal *animal1=[dogFactory createAnimal];
[animal1 laugh];
Animal *animal2=[dogFactory createAnimal];
[animal2 laugh];
…….
Animal *animal100=[dogFactory createAnimal];
[animal100 laugh];
這樣話(huà)如果要把100個(gè)Dog改為Cat的話(huà),只需要吧DogFactory改為CatFactory就可以了
?
但是工廠方法也有它的限制:
1.要?jiǎng)?chuàng)建的類(lèi)必須擁有同一個(gè)父類(lèi)
2.要?jiǎng)?chuàng)建的類(lèi)在100個(gè)不同的地方所調(diào)用的方法必須一樣
以上這些只是個(gè)人感悟,會(huì)有一些不足的地方,請(qǐng)大家?guī)兔Ω恼?#xff0c;嘿嘿
轉(zhuǎn)載于:https://www.cnblogs.com/lion-witcher/p/6377296.html
總結(jié)
以上是生活随笔為你收集整理的iOS中都有什么设计模式?各个设计模式的作用 (转载)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 23. Spring Boot启动加载数
- 下一篇: rman学习笔记部分