一.OC的三大特性
封裝、繼承挽拂、多態(tài)
1> 什么是多態(tài)
多態(tài):不同對象以自己的方式響應相同的消息的能力叫做多態(tài)志膀。
由于每個類都屬于該類的名字空間,這使得多態(tài)稱為可能坐昙。類定義中的名字和類定義外的名字并不會沖突绳匀。類的實例變量和類方法有如下特點:
和C語言中結(jié)構(gòu)體中的數(shù)據(jù)成員一樣,類的實例變量也位于該類獨有的名字空間炸客。
類方法也同樣位于該類獨有的名字空間疾棵。與C語言中的方法名不同,類的方法名并不是一個全局符號痹仙。一個類中的方法名不會和其他類中同樣的方法名沖突是尔。兩個完全不同的類可以實現(xiàn)同一個方法。
方法名是對象接口的一部分开仰。對象收到的消息的名字就是調(diào)用的方法的名字拟枚。因為不同的對象可以有同名的方法,所以對象必須能理解消息的含義抖所。同樣的消息發(fā)給不同的對象梨州,導致的操作并不相同。
多態(tài)的主要好處就是簡化了編程接口田轧。它容許在類和類之間重用一些習慣性的命名暴匠,而不用為每一個新加的函數(shù)命名一個新名字。這樣傻粘,編程接口就是一些抽象的行為的集合每窖,從而和實現(xiàn)接口的類區(qū)分開來。
Objective-C支持方法名的多態(tài)弦悉,但不支持參數(shù)和操作符的多態(tài)窒典。
2>?OC中如何實現(xiàn)多態(tài)
在Objective-C中是通過一個叫做selector的選取器實現(xiàn)的。在Objective-C中稽莉,selector有兩個意思瀑志, 當用在給對象的源碼消息時,用來指方法的名字。它也指那個在源碼編譯后代替方法名的唯一的標識符劈猪。 編譯后的選擇器的類型是SEL有同樣名字的方法昧甘、也有同樣的選擇器。你可以使用選擇器來調(diào)用一個對象的方法战得。
選取器有以下特點:
* 所有同名的方法擁有同樣的選取器
* 所有的選取器都是不一樣的
(1) SEL和@selector
選擇器的類型是?SEL充边。@selector指示符用來引用選擇器,返回類型是SEL常侦。
例如:
SEL?responseSEL;
responseSEL =?@selector(loadDataForTableView:);
可以通過字符串來得到選取器浇冰,例如:
responseSEL =?NSSelectorFromString(@"loadDataForTableView:");
也可以通過反向轉(zhuǎn)換,得到方法名聋亡,例如:
NSString? *methodName =?NSStringFromSelector(responseSEL);
(2) 方法和選取器
選取器確定的是方法名肘习,而不是方法實現(xiàn)。這是多態(tài)性和動態(tài)綁定的基礎(chǔ)杀捻,它使得向不同類對象發(fā)送相同的消息成為現(xiàn)實井厌;否則,發(fā)送???? 消息和標準C中調(diào)用方法就沒有區(qū)別致讥,也就不可能支持多態(tài)性和動態(tài)綁定仅仆。
另外,同一個類的同名類方法和實例方法擁有相同的選取器垢袱。
(3) 方法返回值和參數(shù)類型
消息機制通過選取器找到方法的返回值類型和參數(shù)類型墓拜,因此,動態(tài)綁定(例:向id定義的對象發(fā)送消息)需要同名方法的實現(xiàn)擁有相???? 同返回值類型和相同的參數(shù)類型请契;否則咳榜,運行時可能出現(xiàn)找不到對應方法的錯誤。
有一個例外爽锥,雖然同名類方法和實例方法擁有相同的選取器涌韩,但是它們可以有不同的參數(shù)類型和返回值類型。
3> 動態(tài)綁定
二.類和對象
1.category
1>?分類 拓展 協(xié)議中哪些可以聲明屬性?
都可以,但分類和協(xié)議創(chuàng)建的屬性只相當于方法,但是內(nèi)部沒有對成員變量的操作(無法創(chuàng)建成員變量),拓展可以
代理中聲明屬性,沒有實際創(chuàng)建成員變量,相當于聲明了屬性名對應的訪問方法,遵守協(xié)議的類需要實現(xiàn)對應的訪問器方法,否則運行報錯
分類中聲明屬性,警告提示需要手動實現(xiàn)訪問器方法(Swift中叫計算型屬性),而分類中不能創(chuàng)建成員變量,可以在手寫訪問器方法中使用runtime的 objc_setAssociatedObject方法關(guān)聯(lián)對象間接創(chuàng)建屬性(靜態(tài)庫添加屬性)
拓展里可以聲明屬性,直接可以使用
2>?繼承和類別的區(qū)別
1> 使用繼承:
1.1> 添加新方法和父類方法一致,但父類方法仍需要使用
1.2> 添加新屬性
2> 類別:
2.1> 針對系統(tǒng)提供的一些類,系統(tǒng)本身不提倡繼承,因為這些類的內(nèi)部實現(xiàn)對繼承有所限制(NSString initWithFormat繼承崩潰)
2.2> 類別可以將自己構(gòu)建的類中的方法進行分組,對于大型的類,提高可維護性
3> 分類的作用
將類的實現(xiàn)分散到多個不同文件或多個不同框架中氯夷。
創(chuàng)建對私有方法的前向引用臣樱。
向?qū)ο筇砑臃钦絽f(xié)議。
4> 分類的局限性
無法向類中添加新的實例變量腮考,類別沒有位置容納實例變量雇毫。
名稱沖突,即當類別中的方法與原始類方法名稱沖突時踩蔚,類別具有更高的優(yōu)先級棚放。類別方法將完全取代初始方法從而無法再使用初始方法。
無法添加實例變量的局限可以使用字典對象解決.
三.Foundation
1.字符串
2.NSArray和NSDictionary
1> iOS遍歷數(shù)組/字典的方法
數(shù)組:??for循環(huán)??for in????enumerateObjectsUsingBlock(正序)??? enumerateObjectsWithOptions:usingBlock:(多一個遍歷選項,不保證順序)
字典:
1. for(NSString?*object in [testDic allValues])
2. for(id?akey in [testDic allKeys]){
[sum appendString:[testDic objectForKey:akey]];??}
3.?[testDic enumerateKeysAndObjectsUsingBlock:^(idkey,idobj,BOOL*stop) {
[sum appendString:obj];? } ];
速度:??對于數(shù)組, 增強for最快,普通for和block速度差不多,增強最快是因為增強for語法會對容器里的元素的內(nèi)存地址建立緩沖,遍歷的時候直接從緩沖中取元素地址而不是通過調(diào)用方法來獲取,所以效率高.這也是使用增強for時不能在循環(huán)體中修改容器元素的原因之一(可以在循環(huán)體中添加標記,在循環(huán)體外修改元素)
對于字典,allValues最快,allKey和block差不多,原因是allKey需要做objcetForKey的方法
3.NSValue NSNumber
1> 歸檔視圖尺寸馅闽,坐標
4.其他
nil Nil null NSNull 的區(qū)別
四.關(guān)鍵字
1.@property
一個區(qū)分度很大的面試題
考察一個面試者基礎(chǔ)咋樣飘蚯,基本上問一個 @property 就夠了:
@property 后面可以有哪些修飾符馍迄?
線程安全的:
atomic,nonatomic
訪問權(quán)限的
readonly,readwrite
內(nèi)存管理(ARC)
assign,strong,weak,copy
內(nèi)存管理(MRC)
assign,retain,copy
指定方法名稱
setter=
getter=
1>readwrite,readonly孝冒,assign柬姚,retain,copy庄涡,nonatomic屬性的作用
@property是一個屬性訪問聲明,擴號內(nèi)支持以下幾個屬性:
1.1> getter setter
getter=getterName搬设,setter=setterName穴店,設(shè)置setter與getter的方法名
1.2> weak assign strong copy
assign??用于非指針變量。用于基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger)和C數(shù)據(jù)類型(int, float, double, char, 等),另外還有id,其setter方法直接賦值拿穴,不進行任何retain操作
weak????用于指針變量,比assign多了一個功能,當對象消失后自動把指針變成nil,由于消息發(fā)送給空對象表示無操作,這樣有效的避免了崩潰(野指針),為了解決原類型與循環(huán)引用問題
strong? 用于指針變量,setter方法對參數(shù)進行release舊值再retain新值
copy????用于指針變量,setter方法進行copy操作泣洞,與retain處理流程一樣,先舊值release默色,再copy出新的對象球凰,retainCount為1。這是為了減少對上下文的依賴而引入的機制腿宰。copy是在你不希望a和b共享一塊內(nèi)存時會使用到呕诉。a和b各自有自己的內(nèi)存。
1吃度、什么情況使用 weak 關(guān)鍵字甩挫,相比 assign 有什么不同?比如:
在ARC中,出現(xiàn)循環(huán)引用的時候,必須要有一端使用weak,比如:自定義View的代理屬性
已經(jīng)自身已經(jīng)對它進行一次強應用,沒有必要在強引用一次,此時也會使用weak,自定義View的子控件屬性一般也使用weak;但b是也可以使用strong
weak當對象銷毀的時候,指針會被自動設(shè)置為nil,而assign不會* assigin 可以用非OC對象,而weak必須用于OC對象
2椿每、怎么用 copy 關(guān)鍵字伊者?
對于字符串和block的屬性一般使用copy
字符串使用copy是為了外部把字符串內(nèi)容改了,不影響該屬性
block使用copy是在MRC遺留下來的,在MRC中,方法內(nèi)部的block是在在棧區(qū)的,使用copy可以把它放到堆區(qū).在ACR中對于block使用copy還是strong效果是一樣的
3、這個寫法會出什么問題: @property (copy) NSMutableArray *array;
添加,刪除,修改數(shù)組內(nèi)的元素的時候,程序會因為找不到對于的方法而崩潰.因為copy就是復制一個不可變NSArray的對象
1.3>?readwrite,readonly间护,設(shè)置可供訪問級別
1.4> nonatomic亦渗,非原子性訪問,不加同步汁尺,多線程并發(fā)訪問會提高性能法精。注意,如果不加此屬性均函,則默認是兩個訪問方法都為原子型事務訪問亿虽。所以約定俗成只在主線程更新UI,防止多線程設(shè)置UI屬性,出現(xiàn)資源搶奪現(xiàn)象
2> 如何避免循環(huán)引用
兩個對象相互強引用,都無法release苞也,解決辦法為一個使用strong洛勉,一個使用assign(weak)
3> delegate的屬性為什么使用assign/weak
避免出現(xiàn)循環(huán)引用,場景如UITableViewController強引用視圖UITableView,而該視圖的代理又是控制器如迟,為避免循環(huán)引用收毫,讓delegate為弱引用
2.copy
1> copy的使用場景
當多個指針指向同一個對象時,為避免一個指針對對象的改動對其他指針的使用產(chǎn)生影響,使用copy來創(chuàng)建對象的副本
如頁面間傳值使用copy,A向B控制器傳屬性(屬性為自定義對象),為避免因A的屬性變化對B的屬性產(chǎn)生影響
再如多人開發(fā)或封裝庫,在不明確傳入值為可變還是不可變的情況下,使用copy更安全
2> 什么是深拷貝淺拷貝
對于非容器類對象,不可變對象進行copy操作為淺拷貝,引用計數(shù)器加1,其他三種為深拷貝
對于容器類對象,基本和非容器類對象一致,但注意其深拷貝是對象本身是對象復制,其中元素仍為指針復制,系統(tǒng)將initWithArray方法歸為了元素深拷貝,但其實如果元素為不可變元素,仍為指針復制,使用歸解檔可以實現(xiàn)真正的深拷貝,元素也是對象拷貝NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: array]];
3> 字符串什么時候使用copy,strong
屬性引用的對象由兩種情況,可變和不可變字符串
引用對象不可變情況下,copy和strong一樣,copy為淺拷貝
引用對象可變情況下,如果希望屬性跟隨引用對象變化,使用strong,希望不跟隨變化使用copy
4> 字符串所在內(nèi)存區(qū)域
@“abc” 常量區(qū)?? stringwithformat 堆區(qū)
5> mutablecopy和copy????@property(copy) NSMutableArray *arr;這樣寫有什么問題
mutablecopy返回可變對象,copy返回不可變對象
6> 如何讓自定義類可以使用copy修飾符
實現(xiàn)協(xié)議,重寫copyWithZone方法
五.runtime/消息轉(zhuǎn)發(fā)機制
1.runtimehttp://www.cocoachina.com/ios/20150715/12540.html
1> 什么是runtime
runtime是一套比較底層的純C語言API, 屬于1個C語言庫, 包含了很多底層的C語言API攻走。
在我們平時編寫的OC代碼中, 程序運行過程時, 其實最終都是轉(zhuǎn)成了runtime的C語言代碼, runtime算是OC的幕后工作者,objc_msgSend
2> runtime干什么用,使用場景
runtime是屬于OC的底層, 可以進行一些非常底層的操作(用OC是無法現(xiàn)實的, 不好實現(xiàn))
在程序運行過程中, 動態(tài)創(chuàng)建一個類(比如KVO的底層實現(xiàn))??objc_allocateClassPair,class_addIvar此再,objc_registerClassPair
在程序運行過程中, 動態(tài)地為某個類添加屬性\方法, 修改屬性值\方法(修改封裝的框架)??objc_setAssociatedObject?? object_setIvar
遍歷一個類的所有成員變量(屬性)\所有方法(字典轉(zhuǎn)模型,歸解檔)??class_copyIvarList class_copyPropertyList??class_copyMethodList
2.消息機制
1> 消息轉(zhuǎn)發(fā)的原理
當向一個對象發(fā)送消息時昔搂,objc_msgSend方法根據(jù)對象的isa指針找到對象的類,然后在類的調(diào)度表(dispatch table)中查找selector输拇。如果無法找到selector摘符,objc_msgSend通過指向父類的指針找到父類,并在父類的調(diào)度表(dispatch table)中查找selector策吠,以此類推直到NSObject類逛裤。一旦查找到selector,objc_msgSend方法根據(jù)調(diào)度表的內(nèi)存地址調(diào)用該實現(xiàn)猴抹。 通過這種方式带族,message與方法的真正實現(xiàn)在執(zhí)行階段才綁定。
為了保證消息發(fā)送與執(zhí)行的效率蟀给,系統(tǒng)會將全部selector和使用過的方法的內(nèi)存地址緩存起來蝙砌。每個類都有一個獨立的緩存,緩存包含有當前類自己的 selector以及繼承自父類的selector跋理。查找調(diào)度表(dispatch table)前择克,消息發(fā)送系統(tǒng)首先檢查receiver對象的緩存。
緩存命中的情況下薪介,消息發(fā)送(messaging)比直接調(diào)用方法(function call)只慢一點點點點祠饺。
2> SEL isa?super cmd 是什么
sel: 一種類型,表示方法名稱,類似字符串(可互轉(zhuǎn))
isa:在方法底層對應的objc_msgSend調(diào)用時,會根據(jù)isa找到對象所在的類對象,類對象中包含了調(diào)度表(dispatch table),該表將類的sel和方法的實際內(nèi)存地址關(guān)聯(lián)起來
super_class:每一個類中還包含了一個super_class指針,用來指向父類對象
_cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法調(diào)用的對象實例
IMP定義為?id?(*IMP) (id,?SEL, …)汁政。這樣說來道偷,?IMP是一個指向函數(shù)的指針,這個被指向的函數(shù)包括id(“self”指針)记劈,調(diào)用的SEL(方法名)勺鸦,再加上一些其他參數(shù).說白了IMP就是實現(xiàn)方法
3> 動態(tài)綁定
—在運行時確定要調(diào)用的方法
動態(tài)綁定將調(diào)用方法的確定也推遲到運行時。在編譯時目木,方法的 調(diào)用并不和代碼綁定在一起换途,只有在消實發(fā)送出來之后,才確定被調(diào)用的代碼刽射。通過動態(tài)類型和動態(tài)綁定技術(shù)军拟,您的代碼每次執(zhí)行都可以得到不同的結(jié)果。運行時因 子負責確定消息的接收者和被調(diào)用的方法誓禁。運行時的消息分發(fā)機制為動態(tài)綁定提供支持懈息。當您向一個動態(tài)類型確定了的對象發(fā)送消息時,運行環(huán)境系統(tǒng)會通過接收者 的isa指針定位對象的類摹恰,并以此為起點確定被調(diào)用的方法辫继,方法和消息是動態(tài)綁定的怒见。而且,您不必在Objective-C 代碼中做任何工作姑宽,就可以自動獲取動態(tài)綁定的好處遣耍。您在每次發(fā)送消息時,特別是當消息的接收者是動態(tài)類型已經(jīng)確定的對象時炮车,動態(tài)綁定就會例行而透明地發(fā)生舵变。
5>?通知的內(nèi)存管理 線程問題
六.數(shù)據(jù)傳遞
1.block
1>?block屬性為什么用copy?
棧->堆
2> block使用注意什么?
循環(huán)引用??修改外部變量
3> block的主要使用場景 ?
動畫
數(shù)組字典排序遍歷
回調(diào)狀態(tài)
錯誤控制
多線程GCD
4>block原理
block屬性是指向結(jié)構(gòu)體的指針,
2.Delegate
1>?什么時候用delegate瘦穆,什么時候用Notification
delegate針對one-to-one關(guān)系棋傍,并且reciever可以返回值給sender,notification 可以針對one-to-one/many/none,reciever無法返回值給sender.所以,delegate用于sender希望接受到 reciever的某個功能反饋值难审,notification用于通知多個object某個事件。
2> delegate和block
block使代碼更緊湊,便于閱讀,delegate可以設(shè)置必選和可選的方法實現(xiàn),相比block
block可以訪存局部變量.?不需要像以前的回調(diào)一樣亿絮,把在操作后所有需要用到的數(shù)據(jù)封裝成特定的數(shù)據(jù)結(jié)構(gòu), 你完全可以直接訪問局部變量.
3.KVC和KVO
1> 如何調(diào)用私有變量????如何修改系統(tǒng)的只讀屬性????KVC的查找順序
KVC在某種程度上提供了訪問器的替代方案告喊。不過訪問器方法是一個很好的東西,以至于只要是有可能派昧,KVC也盡量再訪問器方法的幫助下工作黔姜。為了設(shè)置或者返回對象屬性,KVC按順序使用如下技術(shù):
①檢查是否存在-蒂萎、-is(只針對布爾值有效)或者-get的訪問器方法秆吵,如果有可能,就是用這些方法返回值五慈;
檢查是否存在名為-set:的方法纳寂,并使用它做設(shè)置值。對于 -get和 -set:方法泻拦,將大寫Key字符串的第一個字母毙芜,并與Cocoa的方法命名保持一致;
②如果上述方法不可用争拐,則檢查名為-_腋粥、-_is(只針對布爾值有效)、-_get和-_set:方法架曹;
③如果沒有找到訪問器方法隘冲,可以嘗試直接訪問實例變量。實例變量可以是名為:或_;
④如果仍為找到绑雄,則調(diào)用valueForUndefinedKey:和setValue:forUndefinedKey:方法展辞。這些方法的默認實現(xiàn)都是拋出異常,我們可以根據(jù)需要重寫它們绳慎。
2> 什么是鍵-值,鍵路徑是什么
模型的性質(zhì)是通過一個簡單的鍵(通常是個字符串)來指定的纵竖。視圖和控制器通過鍵來查找相應的屬性值漠烧。在一個給定的實體中,同一個屬性的所有值具有相同的數(shù)據(jù)類型靡砌。鍵-值編碼技術(shù)用于進行這樣的查找—它是一種間接訪問對象屬性的機制已脓。
鍵路徑是一個由用點作分隔符的鍵組成的字符串,用于指定一個連接在一起的對象性質(zhì)序列通殃。第一個鍵的性質(zhì)是由先前的性質(zhì)決定的度液,接下來每個鍵的值也是相對于其前面的性質(zhì)。鍵路徑使您可以以獨立于模型實現(xiàn)的方式指定相關(guān)對象的性質(zhì)画舌。通過鍵路徑堕担,您可以指定對象圖中的一個任意深度的路徑,使其指向相關(guān)對象的特定屬性曲聂。
3>?什么是KVC和KVO
KVC(Key-Value-Coding)內(nèi)部的實現(xiàn):一個對象在調(diào)用setValue的時候霹购,(1)首先根據(jù)方法名找到運行方法的時候所需要的環(huán)境參數(shù)。(2)他會從自己isa指針結(jié)合環(huán)境參數(shù)朋腋,找到具體的方法實現(xiàn)的接口齐疙。(3)再直接查找得來的具體的方法實現(xiàn)。KVO(Key-Value- Observing):當觀察者為一個對象的屬性進行了注冊旭咽,被觀察對象的isa指針被修改的時候贞奋,isa指針就會指向一個中間類,而不是真實的類穷绵。所以 isa指針其實不需要指向?qū)嵗龑ο笳鎸嵉念惤嗡K晕覀兊某绦蜃詈貌灰蕾囉趇sa指針。在調(diào)用類的方法的時候仲墨,最好要明確對象實例的類名
4> kvo的實現(xiàn)機制
當某個類的對象第一次被觀察時勾缭,系統(tǒng)就會在運行時動態(tài)地創(chuàng)建該類的一個派生類,在這個派生類中重寫原類中被觀察屬性的setter方法,派生類在被重寫的setter方法實現(xiàn)真正的通知機制(Person->NSKVONotifying_Person).
派生類重寫了 class 方法以“欺騙”外部調(diào)用者它就是起初的那個類宗收。然后系統(tǒng)將這個對象的isa指針指向這個新誕生的派生類漫拭,因此這個對象就成為該派生類的對象了,因而在該對象上對setter的調(diào)用就會調(diào)用重寫的setter混稽,從而激活鍵值通知機制采驻。此外,派生類還重寫了dealloc方法來釋放資源匈勋。
5> kvo使用場景
①實現(xiàn)上下拉刷新控件 contentoffset
②webview混合排版 contentsize
③監(jiān)聽模型屬性實時更新UI
六.設(shè)計模式
1> 常用的設(shè)計模式
代理??觀察者??工廠??單例?? 策略
2> 代理屬性的內(nèi)存策略是什么,為什么?
3> 觀察者模式的使用場景
4> 工廠模式(類方法)為什么沒有釋放對象? autorelease工作原理? arc下還需要手動使用autorelease嗎?為什么?什么場景?
5> 手寫單例
6> 策略??cell多種響應效果?? 代理方法
(一)代理模式
應用場景:當一個類的某些功能需要由別的類來實現(xiàn)礼旅,但是又不確定具體會是哪個類實現(xiàn)。
優(yōu)勢:解耦合
敏捷原則:開放-封閉原則
實例:tableview的數(shù)據(jù)源delegate洽洁,通過和protocol的配合痘系,完成委托訴求。
列表row個數(shù)delegate
自定義的delegate
(二)觀察者模式
應用場景:一般為model層對controller和view進行的通知方式饿自,不關(guān)心誰去接收汰翠,只負責發(fā)布信息龄坪。
優(yōu)勢:解耦合
敏捷原則:接口隔離原則,開放-封閉原則
實例:Notification通知中心复唤,注冊通知中心健田,任何位置可以發(fā)送消息,注冊觀察者的對象可以接收佛纫。
kvo妓局,鍵值對改變通知的觀察者,平時基本沒用過呈宇。
(三)MVC模式
應用場景:是一中非常古老的設(shè)計模式好爬,通過數(shù)據(jù)模型,控制器邏輯甥啄,視圖展示將應用程序進行邏輯劃分存炮。
優(yōu)勢:使系統(tǒng),層次清晰蜈漓,職責分明僵蛛,易于維護
敏捷原則:對擴展開放-對修改封閉
實例:model-即數(shù)據(jù)模型,view-視圖展示迎变,controller進行UI展現(xiàn)和數(shù)據(jù)交互的邏輯控制。
(四)單例模式
應用場景:確保程序運行期某個類飘言,只有一份實例衣形,用于進行資源共享控制。
優(yōu)勢:使用簡單姿鸿,延時求值谆吴,易于跨模塊
敏捷原則:單一職責原則
實例:[UIApplication sharedApplication]。
注意事項:確保使用者只能通過getInstance方法才能獲得苛预,單例類的唯一實例句狼。
java,C++中使其沒有公有構(gòu)造函數(shù)热某,私有化并覆蓋其構(gòu)造函數(shù)腻菇。
object c中,重寫allocWithZone方法昔馋,保證即使用戶用alloc方法直接創(chuàng)建單例類的實例筹吐,返回的也只是此單例類的唯一靜態(tài)變量。
(五)策略模式
應用場景:定義算法族秘遏,封裝起來丘薛,使他們之間可以相互替換。
優(yōu)勢:使算法的變化獨立于使用算法的用戶
敏捷原則:接口隔離原則邦危;多用組合洋侨,少用繼承舍扰;針對接口編程,而非實現(xiàn)希坚。
實例:排序算法边苹,NSArray的sortedArrayUsingSelector;經(jīng)典的鴨子會叫吏够,會飛案例勾给。
注意事項:
1,剝離類中易于變化的行為锅知,通過組合的方式嵌入抽象基類
2播急,變化的行為抽象基類為,所有可變變化的父類
3售睹,用戶類的最終實例桩警,通過注入行為實例的方式,設(shè)定易變行為
防止了繼承行為方式昌妹,導致無關(guān)行為污染子類捶枢。完成了策略封裝和可替換性。
(六)工廠模式
應用場景:工廠方式創(chuàng)建類的實例飞崖,多與proxy模式配合烂叔,創(chuàng)建可替換代理類。
優(yōu)勢:易于替換固歪,面向抽象編程蒜鸡,application只與抽象工廠和易變類的共性抽象類發(fā)生調(diào)用關(guān)系。
敏捷原則:DIP依賴倒置原則
實例:項目部署環(huán)境中依賴多個不同類型的數(shù)據(jù)庫時牢裳,需要使用工廠配合proxy完成易用性替換
注意事項:項目初期逢防,軟件結(jié)構(gòu)和需求都沒有穩(wěn)定下來時,不建議使用此模式蒲讯,因為其劣勢也很明顯忘朝,
增加了代碼的復雜度,增加了調(diào)用層次判帮,增加了內(nèi)存負擔局嘁。所以要注意防止模式的濫用。