iOS中都有什么設(shè)計(jì)模式?各個(gè)設(shè)計(jì)模式的作用拨扶?

一 ?iOS中都有什么設(shè)計(jì)模式凳鬓?

1.代理模式

2.觀察者模式

3.MVC模式

4.單例模式

5.策略模式

6.工廠模式

二 ?各個(gè)設(shè)計(jì)模式的作用?

(一)代理模式

在觀察者模式中患民,一個(gè)對象任何狀態(tài)的變更都會(huì)通知另外的對改變感興趣的對象缩举。這些對象之間不需要知道彼此的存在,這其實(shí)是一種松耦合的設(shè)計(jì)匹颤。當(dāng)某個(gè)屬性變化的時(shí)候仅孩,我們通常使用這個(gè)模式去通知其它對象。

此模式的通用實(shí)現(xiàn)中印蓖,觀察者注冊自己感興趣的其它對象的狀態(tài)變更事件杠氢。當(dāng)狀態(tài)發(fā)生變化的時(shí)候,所有的觀察者都會(huì)得到通知另伍。蘋果的推送通知(Push Notification)就是一個(gè)此模式的例子鼻百。

如果你要遵從MVC模式的概念绞旅,你需要讓模型對象和視圖對象在不相互直接引用的情況下通信。這正是觀察者模式的用武之地温艇。

Cocoa通過通知(Notifications)和Key-Value Observing(KVO)來實(shí)現(xiàn)觀察者模式因悲。

在cocoa框架中的Delegate模式中,委托人往往是框架中的對象(視圖中的控件勺爱、表視圖神馬的)晃琳,代理人往往是視圖控制器對象。

在我們這個(gè)例子中UITableView是委托人琐鲁,代理人首先得滿足一個(gè)條件:就是在.h文件中申明它擁有代理資格:

@interface WhateverViewController < UITableViewDelegate >

@end

紅色的表示這個(gè)視圖控制器擁有UITableView的代理資格卫旱。

其次,在.m文件中定義委托人可以讓代理人去代替做的事情:

//視圖控制器來代辦應(yīng)該有多少個(gè)節(jié)- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {? ? return [NSArray count];}

//視圖控制器來代辦某個(gè)節(jié)應(yīng)該有多少行- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {? ? return [[NSArray objectAtIndex:section]count];}// 視圖控制器來代辦負(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;}

// 對特定編輯風(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) {? ? }}

// 可選奈泪,對那些被移動(dòng)欄格作特定操作- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath? ? ? ? toIndexPath:(NSIndexPath *)toIndexPath {}

// 對那些可以移動(dòng)的行返回YES- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {? ? // 如果不想讓欄格移動(dòng)适贸,就返回NO? ? return YES;}

好了,當(dāng)這個(gè)委托人需要辦這些事時(shí)涝桅,代理人自己就站出來幫忙辦了拜姿。這就是ios中的Delegate模式。

二冯遂、自定義的delegate模式

@interface A:UIViewid 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代理委托對象為B

[a Call];

這樣就會(huì)輸出:

你好,我是B

委托模式關(guān)鍵就在于一個(gè)“被”字蕊肥。這個(gè)B是很被動(dòng)的,隨時(shí)就會(huì)被你A Call一下蛤肌。

三晴埂、為什么會(huì)有delegate模式

換句話說,它可以用來解決神馬問題寻定?

當(dāng)一個(gè)類的某些功能需要被別人來實(shí)現(xiàn)儒洛,但是既不明確是些什么功能,又不明確誰來實(shí)現(xiàn)這些功能的時(shí)候狼速,委托模式就可以派上用場琅锻。

例如你可以再寫個(gè)C類,實(shí)現(xiàn)-(void)transparendValue:(NSString*)fromValue {NSLog(@"%@ ,我是C",value); }也是完全可以的向胡。換誰來恼蓬,只要它實(shí)現(xiàn)了這個(gè)方法,我就可以委托它來做這個(gè)事僵芹。

說到底一切都是為了使類之間的耦合性更松散处硬。好的代碼應(yīng)該對擴(kuò)展開放,對修改關(guān)閉拇派。

總結(jié)來自http://blog.sina.com.cn/s/blog_b638dc89010192qu.html

(二)觀察者模式

在軟件開發(fā)中荷辕,無論是那種高級語言中總會(huì)伴隨著一些最為常用的設(shè)計(jì)模式凿跳,即便就如iOS開發(fā)中與我們打交道最多的無非就是單例模式、觀察者模式和工廠模式了疮方,當(dāng)然了其他的設(shè)置模式也同樣存在在編程的很多地方控嗜。下面就就讓我們簡單的了解下觀察者模式吧!

觀察者模式本質(zhì)上時(shí)一種發(fā)布-訂閱模型,用以消除具有不同行為的對象之間的耦合,通過這一模式骡显,不同對象可以協(xié)同工作疆栏,同時(shí)它們也可以被復(fù)用于其他地方Observer從Subject訂閱通知,ConcreteObserver實(shí)現(xiàn)重現(xiàn)ObServer并將其重載其update方法惫谤。一旦SubJect的實(shí)例需要通知Observer任何新的變更壁顶,Subject會(huì)發(fā)送update消息來通知存儲(chǔ)在其內(nèi)部類中所注冊的Observer、在ConcreteObserver的update方法的實(shí)際實(shí)現(xiàn)中溜歪,Subject的內(nèi)部狀態(tài)可被取得并進(jìn)行后續(xù)處理若专。其類圖如下:

觀察者模式.png

由上面我們可以發(fā)現(xiàn)觀察者模式無非在是定義對象間的一種一對多的依賴關(guān)系,并且當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變的時(shí)候痹愚,所有依賴于它的對象都會(huì)得到通知且自動(dòng)更新。即如果Subject允許其他觀察者(實(shí)現(xiàn)了觀察者接口的對象)對這個(gè)Subject的改變進(jìn)行請閱蛔糯,當(dāng)Subject發(fā)送了變化拯腮,那么Subject會(huì)將這個(gè)變化發(fā)送給所有的觀察者,觀察者就能對Subject的變化做出更新蚁飒。其時(shí)序圖如下

觀察者模式2.png

通過上面的觀察我們可以發(fā)現(xiàn)如果用N個(gè)Observer來拓展Subject的行為动壤,這些Observer具有處理存儲(chǔ)在Subject中的信息的特定實(shí)現(xiàn),這樣也就實(shí)現(xiàn)了前面所說的消除不同對象間的耦合的功能了淮逻。

那么了解了這些我們可能就會(huì)更像了解下我們在什么時(shí)候才會(huì)去使用觀察者模式呢琼懊?

當(dāng)需要將改變通知所有的對象時(shí),而你又不知道這些對象的具體類型

改變發(fā)生在同一個(gè)對象中爬早,并需要改變其他對象將相關(guān)的狀態(tài)進(jìn)行更新且不知道有多少個(gè)對象哼丈。

而同樣的在我們?nèi)粘5拈_發(fā)中在Cocoa Touch框架中的的兩種經(jīng)常打交道的技術(shù)KVO與通知都實(shí)現(xiàn)了觀察者模式,所以下面我們討論的重點(diǎn)也就是基于這兩個(gè)方面的筛严。

通知

在之前的博文中曾經(jīng)簡單的提到過一些通知的基礎(chǔ)使用方法醉旦,所以一些基本的使用方法再次就不贅述。言歸正傳桨啃,在Cocoa Touch框架中NSNotificationCenter和NSNotification對象實(shí)現(xiàn)了一對多的模型车胡。通過NSNotificationCenter可以讓對象之間進(jìn)行通訊,即便這些對象之間并不認(rèn)識照瘾。下面我們來看下NSNotificationCenter發(fā)布消息的方法:

NSNotification? * subjectMessage = [NSNotification? notificationWithName:@"subjectMessage"? object:self];NSNotificationCenter? * notificationCenter = [NSNotificationCenter? defaultCenter];

[notificationCenter postNotification:subjectMessage];

通過上面的代碼我們創(chuàng)建了一個(gè)名為subjectMessage的NSNotification對象,然后通過notificationCenter來發(fā)布這個(gè)消息匈棘。通過向NSNotificationCenter類發(fā)送defaulCenter消息,可以得到NSNotificationCenter實(shí)例的引用析命。每個(gè)進(jìn)程中只有一個(gè)默認(rèn)的通知中心主卫,所以默認(rèn)的NSNotificationCenter是個(gè)單例對象逃默。如果有其他觀察者定于了其對象的相關(guān)事件則可以通過以下的方法來進(jìn)行操作:

NSNotificationCenter? * notificationCenter1 = [NSNotificationCenter? defaultCenter];? ? [notificationCenter addObserver:self? selector:@selector(update:) name:@"subjectMessage"? object:nil ];

經(jīng)過以上步驟我們已經(jīng)向通知中心注冊了一個(gè)事件并且通過selector制定了一個(gè)方法update:下面我們可以實(shí)現(xiàn)以下這個(gè)方法

- (void)update:(NSNotification*)notification{if ([[notification name] isEqualToString:@"subjectMessage"]) {NSLog(@"%@",@"猴子派來的救兵去哪了?");

}

}

當(dāng)然最后如果我們需要對監(jiān)聽進(jìn)行銷毀

- (void)dealloc {? ? [[NSNotificationCenter defaultCenter] removeObserver:self];

}

了解過通知之后我們來看一下KVO

KVO是Cocoa提供的一種稱為鍵值觀察的機(jī)制队秩,對象可以通過它得到其他對象特定屬性的變更通知笑旺。而這個(gè)機(jī)制是基于NSKeyValueObserving非正式些,Cocoa通過這個(gè)協(xié)議為所有遵循協(xié)議的對象提供了一種自動(dòng)化的屬性監(jiān)聽的功能馍资。

雖然通知和KVO都可以對觀察者進(jìn)行實(shí)現(xiàn)筒主,但是他們之間還是略有不同的,由上面的例子我們可以看出通知是由一個(gè)中心對象為所有觀察者提供變更通知鸟蟹,主要是廣義上關(guān)注程序事件乌妙,而KVO則是被觀察的對象直接想觀察者發(fā)送通知,主要是綁定于特定對象屬性的值建钥。下面我們通過一個(gè)簡單的例子來了解下他的一些是使用方法

首先我們有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è)對象基本有值了藤韵,那么我們將這個(gè)對象的name監(jiān)聽下他的改變

[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

最后注銷觀察者

- (void)dealloc{? ? [self.hero removeObserver:self forKeyPath:@"name"];

}

到了這里觀察者模式中常用的KVO及通知的內(nèi)容就到這里熊经,不過要知道這里談及的只是最基礎(chǔ)的用法泽艘,后面我們可能還是有更加深入的探究,或者在后續(xù)中可能還會(huì)對比iOS中的代理以及Block來探尋下iOS中的消息傳遞機(jī)制镐依,再或者像Swift中的didSet匹涮、willSet的屬性監(jiān)聽的方法,這些都是很好玩的內(nèi)容槐壳,不是么然低?

(三)MVC模式

MVC根據(jù)角色劃分類,涉及到三個(gè)角色:

Model:模型保存應(yīng)用程序的數(shù)據(jù)务唐。

View:視圖是模型的可視化表示以及用戶交互的控件雳攘。

Controller:控制器是一個(gè)協(xié)調(diào)所有工作的中介者。它訪問模型中的數(shù)據(jù)并在視圖中展示它們枫笛,同時(shí)它們還監(jiān)聽事件和操作數(shù)據(jù)吨灭。

一個(gè)MVC模式的好的實(shí)現(xiàn)也就意味著每一個(gè)對象都會(huì)被劃分到上面所說的組中。

我們可以很好的用下圖來描述通過控制器實(shí)現(xiàn)的視圖到模型的交互過程:

模型會(huì)把任何數(shù)據(jù)的變更通知控制器刑巧,然后控制器更新視圖數(shù)據(jù)沃于。視圖對象通知控制器用戶的操作,控制器要么根據(jù)需要來更新模型海诲,要么檢索任何被請求的數(shù)據(jù)繁莹。

你可能在想為什么不能僅僅使用控制器,在一個(gè)類中實(shí)現(xiàn)視圖和模型特幔,這樣貌似更加容易咨演?

所有的這些都?xì)w結(jié)于代碼關(guān)注點(diǎn)分離以及復(fù)用。在理想的狀態(tài)下蚯斯,視圖應(yīng)該和模型完全的分離薄风。如果視圖不依賴某個(gè)實(shí)際的模型饵较,那么視圖就可以被復(fù)用來展示不同模型的數(shù)據(jù)。

舉個(gè)例子來說遭赂,如果將來你打算加入電影或者書籍到你的資料庫中循诉,你仍然可以使用同樣的AlbumView去顯示電影和書籍?dāng)?shù)據(jù)。更進(jìn)一步來說撇他,如果你想創(chuàng)建一個(gè)新的與專輯有關(guān)聯(lián)的工程茄猫,你可以很簡單的復(fù)用Album類,因?yàn)樗灰蕾嚾魏我晥D困肩。這就是MVC的強(qiáng)大之處划纽。

(四)單例模式

單例設(shè)計(jì)模式確保對于一個(gè)給定的類只有一個(gè)實(shí)例存在,這個(gè)實(shí)例有一個(gè)全局唯一的訪問點(diǎn)锌畸。它通常采用懶加載的方式在第一次用到實(shí)例的時(shí)候再去創(chuàng)建它勇劣。

注意:蘋果大量使用了此模式。例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager]潭枣,所有的這些方法都返回一個(gè)單例對象比默。

你很可能會(huì)想為什么這么關(guān)心是否一個(gè)類有多個(gè)實(shí)例?畢竟代碼和內(nèi)存都是廉價(jià)的盆犁,對嗎命咐?

有一些情況下,只有一個(gè)實(shí)例顯得非常合理蚣抗。舉例來說侈百,你不需要有多個(gè)Logger的實(shí)例瓮下,除非你想去寫多個(gè)日志文件翰铡。或者一個(gè)全局的配置處理類:實(shí)現(xiàn)線程安全的方式訪問共享實(shí)例是容易的讽坏,比如一個(gè)配置文件锭魔,有好多個(gè)類同時(shí)修改這個(gè)文件。

(五)策略模式

1.概述

在軟件開發(fā)中也常常遇到類似的情況路呜,實(shí)現(xiàn)某一個(gè)功能有多種算法或者?策略迷捧,我們可以根據(jù)環(huán)境或者條件的不同選擇不同的算法或者策略來完成該功能?。如查找胀葱、排序等漠秋,一種常用的方法是硬編碼(Hard Coding)在一個(gè)類中,如需要提供多種查找算法抵屿,可以將這些算法寫到一個(gè)類中庆锦,在該類中提供多個(gè)方法,每一個(gè)方法對應(yīng)一個(gè)具體的查找算法轧葛;當(dāng)然也可以將這些查找算法封裝在一個(gè)統(tǒng)一的方法中搂抒,通過if…else…或者?case?等條件判斷語句來進(jìn)行選擇艇搀。這兩種實(shí)現(xiàn)方法我們都可以稱之為硬編碼,如果需要增加一種新的查找算法求晶,需要修改封裝算法類的源代碼焰雕;更換查找算法,也需要修改客戶端調(diào)用代碼芳杏。在這個(gè)算法類中封裝了大量查找算法矩屁,?該類代碼將較復(fù)雜,維護(hù)較為困難蚜锨。如果我們將這些策略包含在客戶端?档插,這種做法更不可取,將導(dǎo)致客戶端程序龐大而且難以維護(hù)亚再,如果存在大量可供選擇的算法時(shí)問題將變得更加嚴(yán)重郭膛。

例子1:一個(gè)菜單功能能夠根據(jù)用戶的“皮膚”首選項(xiàng)來決定是否采用水平的還是垂直的排列形式。同事可以靈活增加菜單那的顯示樣式氛悬。

例子2:出行旅游:我們?可以有幾個(gè)策略可以考慮:可以騎自行車则剃,汽車,做火車如捅,飛機(jī)棍现。每個(gè)策略都可以得到相同的結(jié)果,但是它們使用了不同的資源镜遣。選擇策略的依據(jù)是費(fèi)用己肮,時(shí)間,使用工具還有每種方式的方便程度 悲关。

2.問題

如何讓算法和對象分開來谎僻,使得算法可以獨(dú)立于使用它的客戶而變化?

3.解決方案

策略模式:?定義一系列的算法,把每一個(gè)算法封裝起來, 并且使它們可相互替換寓辱。本模式使得算法可獨(dú)立于使用它的客戶而變化艘绍。也稱為?政策模式?(Policy)。(?Definea family of algorithms,encapsulate each one, andmake them interchangeable. Strategy lets the algorithmvary independently from clients that use it.??)

策略模式把對象本身和運(yùn)算規(guī)則區(qū)分開來秫筏,其?功能非常強(qiáng)大诱鞠,因?yàn)檫@個(gè)設(shè)計(jì)模式本身的核心思想就是面向?qū)ο缶幊痰亩嘈涡缘乃枷搿?/p>

4.適用性

當(dāng)存在以下情況時(shí)使用Strategy模式

1)? 許多相關(guān)的類僅僅是行為有異。 “策略”提供了一種用多個(gè)行為中的一個(gè)行為來配置一個(gè)類的方法这敬。即一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種航夺。

2)? 需要使用一個(gè)算法的不同變體。例如崔涂,你可能會(huì)定義一些反映不同的空間 /時(shí)間權(quán)衡的算法阳掐。當(dāng)這些變體實(shí)現(xiàn)為一個(gè)算法的類層次時(shí) ,可以使用策略模式。

3)? 算法使用客戶不應(yīng)該知道的數(shù)據(jù)∶常可使用策略模式以避免暴露復(fù)雜的觅闽、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)。

4)? 一個(gè)類定義了多種行為 , 并且這些行為在這個(gè)類的操作中以多個(gè)條件語句的形式出現(xiàn)涮俄。將相關(guān)的條件分支移入它們各自的Strategy類中以代替這些條件語句蛉拙。

5.結(jié)構(gòu)

6.效果

Strategy模式有下面的一些優(yōu)點(diǎn):

1) 相關(guān)算法系列

Strategy類層次為Context定義了一系列的可供重用的算法或行為。?繼承有助于析取出這些算法中的公共功能彻亲。

2) 提供了可以替換繼承關(guān)系的辦法

: 繼承提供了另一種支持多種算法或行為的方法孕锄。你可以直接生成一個(gè)Context類的子類,從而給它以不同的行為苞尝。但這會(huì)將行為硬行編制到 Context中畸肆,而將算法的實(shí)現(xiàn)與Context的實(shí)現(xiàn)混合起來,從而使Context難以理解、難以維護(hù)和難以擴(kuò)展宙址,而且還不能動(dòng)態(tài)地改變算法轴脐。最后你得到一堆相關(guān)的類 , 它們之間的唯一差別是它們所使用的算法或行為。?將算法封裝在獨(dú)立的Strategy類中使得你可以獨(dú)立于其Context改變它抡砂,使它易于切換大咱、易于理解、易于擴(kuò)展注益。

3) 消除了一些if else條件語句

:Strategy模式提供了用條件語句選擇所需的行為以外的另一種選擇碴巾。當(dāng)不同的行為堆砌在一個(gè)類中時(shí) ,很難避免使用條件語句來選擇合適的行為。將行為封裝在一個(gè)個(gè)獨(dú)立的Strategy類中消除了這些條件語句丑搔。含有許多條件語句的代碼通常意味著需要使用Strategy模式厦瓢。

4) 實(shí)現(xiàn)的選擇

Strategy模式可以提供相同行為的不同實(shí)現(xiàn)∑≡拢客戶可以根據(jù)不同時(shí)間 /空間權(quán)衡取舍要求從不同策略中進(jìn)行選擇煮仇。

Strategy模式缺點(diǎn):

1)客戶端必須知道所有的策略類,并自行決定使用哪一個(gè)策略類

: ?本模式有一個(gè)潛在的缺點(diǎn)顽冶,就是一個(gè)客戶要選擇一個(gè)合適的Strategy就必須知道這些Strategy到底有何不同欺抗。此時(shí)可能不得不向客戶暴露具體的實(shí)現(xiàn)問題售碳。因此僅當(dāng)這些不同行為變體與客戶相關(guān)的行為時(shí) , 才需要使用Strategy模式强重。

2 ) Strategy和Context之間的通信開銷

:無論各個(gè)ConcreteStrategy實(shí)現(xiàn)的算法是簡單還是復(fù)雜, 它們都共享Strategy定義的接口。因此很可能某些 ConcreteStrategy不會(huì)都用到所有通過這個(gè)接口傳遞給它們的信息贸人;簡單的 ConcreteStrategy可能不使用其中的任何信息间景!這就意味著有時(shí)Context會(huì)創(chuàng)建和初始化一些永遠(yuǎn)不會(huì)用到的參數(shù)。如果存在這樣問題 , 那么將需要在Strategy和Context之間更進(jìn)行緊密的耦合艺智。

3 )策略模式將造成產(chǎn)生很多策略類

:可以通過使用享元模式在一定程度上減少對象的數(shù)量倘要。 增加了對象的數(shù)目 Strategy增加了一個(gè)應(yīng)用中的對象的數(shù)目。有時(shí)你可以將 Strategy實(shí)現(xiàn)為可供各Context共享的無狀態(tài)的對象來減少這一開銷。任何其余的狀態(tài)都由 Context維護(hù)封拧。Context在每一次對Strategy對象的請求中都將這個(gè)狀態(tài)傳遞過去志鹃。共享的 Strategy不應(yīng)在各次調(diào)用之間維護(hù)狀態(tài)。

7. iOS應(yīng)用分析

例如泽西,我們在驗(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方法承匣,這樣就不用我們在判斷輸入是否合法的時(shí)候通過if else去處理每種邏輯,而且這樣做方便擴(kuò)展锤悄,提高可復(fù)用性韧骗。

實(shí)例:排序算法,NSArray的sortedArrayUsingSelector零聚;經(jīng)典的鴨子會(huì)叫袍暴,會(huì)飛案例。

(六)工廠模式

工廠模式我的理解是:他就是為了創(chuàng)建對象的

創(chuàng)建對象的時(shí)候隶症,我們一般是alloc一個(gè)對象政模,如果需要?jiǎng)?chuàng)建100個(gè)這樣的對象,如果是在一個(gè)for循環(huán)中還好說蚂会,直接一句alloc就行了淋样,但是事實(shí)并不那么如意,我們可能會(huì)在不同的地方去創(chuàng)建這個(gè)對象胁住,那么我們可能需要寫100句alloc 了趁猴,但是如果我們在創(chuàng)建對象的時(shí)候,需要在這些對象創(chuàng)建完之后彪见,為它的一個(gè)屬性添加一個(gè)固定的值儡司,比方說都是某某學(xué)校的學(xué)生,那么可能有需要多些100行重復(fù)的代碼了余指,那么捕犬,如果寫一個(gè)-(void)createObj方法,把創(chuàng)建對象和學(xué)校屬性寫在這個(gè)方法里邊,那么就是會(huì)省事很多碉碉,也就是說我們可以alloc 創(chuàng)建對象封裝到一個(gè)方法里邊柴钻,直接調(diào)用這個(gè)方法就可以了,這就是簡單工廠方法

代碼結(jié)構(gòu)如下

Animal 類

@interface Animal :NSObject

@proterty(nonatomic,strong) NSString *name;

-(void)laugh;

@end

Dog類

@interface Dog:Animal

@end

Cat類

@interface?Cat:Animal

@end

創(chuàng)建對象的工廠類

.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];

這是簡單工廠模式

現(xiàn)在創(chuàng)建100個(gè)Dog對象垢粮,如果這100個(gè)對象寫在程序中的不同地方顿颅,按上邊的方法是需要把Dog *dog=[AnimalFactory createDog];這一句話寫在程序中很多不同的地方,那么現(xiàn)在有一個(gè)需求足丢,就是如果需要把這些創(chuàng)建的100個(gè)Dog對象全部變成Cat對象粱腻,那么按照剛才的那個(gè)做法,就需要在這100句代碼中把createDog方法變成createCat方法了斩跌,這樣做還是很復(fù)雜

那么這個(gè)時(shí)候用工廠方法模式就能解決這個(gè)難題了

工廠方法模式是為每一個(gè)要?jiǎng)?chuàng)建的對象所在的類都相應(yīng)地創(chuàng)建一個(gè)工廠

代碼如下

@interface?AnimalFactory:NSObject

-(Animal*)createAnimal;

@end;

Dog工廠類

@interface DogFactory:AnimalFactory;

@implementation DogFactory

-(Animal *)createAnimal{

retrurn [[Dog alloc]init];

}

@end

Cat工廠類

@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];

這樣話如果要把100個(gè)Dog改為Cat的話绍些,只需要吧DogFactory改為CatFactory就可以了

但是工廠方法也有它的限制:

1.要?jiǎng)?chuàng)建的類必須擁有同一個(gè)父類

2.要?jiǎng)?chuàng)建的類在100個(gè)不同的地方所調(diào)用的方法必須一樣

以上這些只是個(gè)人感悟,會(huì)有一些不足的地方耀鸦,請大家?guī)兔Ω恼砼俸?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市袖订,隨后出現(xiàn)的幾起案子氮帐,更是在濱河造成了極大的恐慌,老刑警劉巖洛姑,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件上沐,死亡現(xiàn)場離奇詭異,居然都是意外死亡楞艾,警方通過查閱死者的電腦和手機(jī)参咙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來硫眯,“玉大人蕴侧,你說我怎么就攤上這事×饺耄” “怎么了净宵?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長裹纳。 經(jīng)常有香客問我择葡,道長,這世上最難降的妖魔是什么痊夭? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任刁岸,我火速辦了婚禮脏里,結(jié)果婚禮上她我,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好番舆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布酝碳。 她就那樣靜靜地躺著,像睡著了一般恨狈。 火紅的嫁衣襯著肌膚如雪疏哗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天禾怠,我揣著相機(jī)與錄音返奉,去河邊找鬼。 笑死吗氏,一個(gè)胖子當(dāng)著我的面吹牛芽偏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弦讽,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼污尉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了往产?” 一聲冷哼從身側(cè)響起被碗,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仿村,沒想到半個(gè)月后锐朴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔼囊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年包颁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片压真。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娩嚼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滴肿,到底是詐尸還是另有隱情岳悟,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布泼差,位于F島的核電站贵少,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏堆缘。R本人自食惡果不足惜滔灶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吼肥。 院中可真熱鬧录平,春花似錦麻车、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至表箭,卻和暖如春赁咙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背免钻。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工彼水, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人极舔。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓猿涨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親姆怪。 傳聞我的和親對象是個(gè)殘疾皇子叛赚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容