性能與對(duì)象訪問,顧名思義就是提高性能和提供對(duì)象訪問。
涉及到性能與對(duì)象訪問的有以下兩種設(shè)計(jì)模式:
① 享元(通過共享資源)
② 代理(通過把操作推遲給代理對(duì)象來提高性能并提供對(duì)象訪問)
一. 享元
在面向?qū)ο蟮脑O(shè)計(jì)中糊肤,利用公共對(duì)象不僅能節(jié)省資源還能提高性能践叠。比如,某個(gè)人物需要一個(gè)類的一百萬個(gè)實(shí)例焦匈,但我們可以把這個(gè)類的一個(gè)實(shí)例讓大家共享赘淮,而把某些獨(dú)特的信息放在外部辕录,節(jié)省的資源可能相當(dāng)可觀。共享的對(duì)象只提供某些內(nèi)在的信息梢卸,而不能用來識(shí)別對(duì)象走诞。
實(shí)現(xiàn)共享模式需要兩個(gè)關(guān)鍵組件,通常是可共享的享元對(duì)象和保存它們的池低剔。某種中央對(duì)象(管理器速梗,或者叫工廠,它維護(hù)池中的享元單元襟齿,通過工廠方法返回享元對(duì)象)維護(hù)這個(gè)池。某些對(duì)象的獨(dú)特狀態(tài)(外在狀態(tài))可以拿到外部
枕赵,在別處管理猜欺,其余部分被共享,這樣我們只需要一個(gè)共同的實(shí)例拷窜,從而節(jié)省內(nèi)存开皿,提高性能。
Flyweight是兩個(gè)具體享元類ConcreteFlyweight1和ConcreteFlyweight2的父接口(基類或協(xié)議)篮昧。每個(gè)ConcreteFlyweight類維護(hù)不能用于識(shí)別對(duì)象的內(nèi)在狀態(tài)intrinsicState(不變的屬性)赋荆。Flyweight聲明了operation:extrinsicState
,由這兩個(gè)ConcreteFlyweight類實(shí)現(xiàn)懊昨。intrinsicState是享元對(duì)象中可被共享的部分窄潭,而extrinsicState補(bǔ)充缺少的信息,讓享元對(duì)象唯一酵颁〖的悖客戶端向operation:extrinsicState
消息提供extrinsicState,讓享元對(duì)象使用extrinsicState中的獨(dú)一無二的信息完成其任務(wù)躏惋。
在Cocoa Touch框架中幽污,我們常用的UITableViewCell就是使用享元模式,我們從緩存池中拿出Cell簿姨,賦值展示所需的模型距误,其中賦值給Cell的模型就是extrinsicState,intrinsicState是它固定的屬性,比如ImageView准潭,Label攘乒。所以說,分享相同的資源以執(zhí)行任務(wù)惋鹅,可能比使用個(gè)人的資源完成同樣的事情更加高效则酝。(分享是人類的美德啊)
在以下情況闰集,需要考慮享元模式:(其實(shí)沽讹,下面都是考慮能不能共用一個(gè)實(shí)例∥渎常看能不能把不同點(diǎn)抽出爽雄,共同點(diǎn)放在一個(gè)實(shí)例共用)
- 應(yīng)用程序使用很多對(duì)象。
- 在內(nèi)存中保存對(duì)象會(huì)影響內(nèi)存性能沐鼠。
- 對(duì)象的多數(shù)特有狀態(tài)(外在狀態(tài))可以放在外部而輕量化挚瘟。
- 移除外在狀態(tài)后,可以用較少的共享對(duì)象替代原來的那組對(duì)象饲梭。
-應(yīng)用程序不依賴對(duì)象標(biāo)識(shí)乘盖,因?yàn)楣蚕韺?duì)象不能提供唯一的標(biāo)識(shí)。
二. 代理
有的人常把委托認(rèn)為是代理模式憔涉,其實(shí)不然订框。代理可以認(rèn)為是代理人(或者認(rèn)為是經(jīng)紀(jì)人),有人需要洽談合作時(shí)兜叨,先找經(jīng)紀(jì)人穿扳,而不是直接找明星,重要合作時(shí)才會(huì)通過經(jīng)紀(jì)人找到明星国旷。代理的一個(gè)常見用處是作為一個(gè)輕量的替身對(duì)象矛物,它允許客戶端先訪問某些廉價(jià)的信息或功能,直到值得或需要使用“真貨”時(shí)跪但,代理才會(huì)去為客戶端準(zhǔn)備真正的履羞、高價(jià)的資源(就像某些收費(fèi)軟件提供免費(fèi)試用期一樣)。
代理通常是一種替代或者占位特漩,它控制對(duì)另一些對(duì)象的訪問吧雹,而這些對(duì)象可能是遠(yuǎn)程對(duì)象,創(chuàng)建開銷較大的對(duì)象涂身,或者是對(duì)安全性有要求的對(duì)象雄卷。有以下幾種代理:
遠(yuǎn)程代理:為位于不同地址空間或網(wǎng)絡(luò)上的對(duì)象提供本地代表。
虛擬代理:根據(jù)需要?jiǎng)?chuàng)建重型對(duì)象蛤售。
保護(hù)代理:根據(jù)各種訪問權(quán)限控制對(duì)原對(duì)象的訪問丁鹉。
智能引用代理:通過對(duì)真正對(duì)象的引用進(jìn)行計(jì)數(shù)管理內(nèi)存妒潭,也用于鎖定真正對(duì)象,讓其他對(duì)象不能對(duì)其進(jìn)行修改揣钦。
代理模式的思想是使用一個(gè)基本跟實(shí)體對(duì)象行為相同的代理雳灾。客戶端可以“透明地”使用代理冯凹,即不必知悉所面對(duì)的只是一個(gè)代理而不是實(shí)體對(duì)象谎亩。當(dāng)客戶端請(qǐng)求某些創(chuàng)建的開銷較大的功能時(shí),代理把請(qǐng)求轉(zhuǎn)發(fā)給實(shí)體對(duì)象宇姚,準(zhǔn)備好請(qǐng)求的功能并返回給客戶端匈庭。
如下圖,當(dāng)客戶端想Proxy對(duì)象發(fā)送request消息時(shí)浑劳,Proxy對(duì)象會(huì)把這個(gè)消息轉(zhuǎn)發(fā)給Proxy對(duì)象之中的RealSubject對(duì)象阱持,RealSubject會(huì)實(shí)施實(shí)際的操作間接滿足客戶端的請(qǐng)求。
舉個(gè)例子??:在iOS編程之道中魔熏,用虛擬代理(根據(jù)需要?jiǎng)?chuàng)建重型對(duì)象)懶加載圖像衷咽。一個(gè)列表展示多張圖片,當(dāng)圖片緩存在磁盤時(shí)蒜绽,應(yīng)該先顯示占位符镶骗,再通過后臺(tái)線程去獲取圖片展示。當(dāng)你使用代理模式時(shí)滓窍,就將這些操作封裝在代理類中卖词。
在Cococa Touch框架中,也經(jīng)常使用NSProxy來實(shí)現(xiàn)代理模式吏夯,NSProxy作為占位或替代對(duì)象,也可以實(shí)現(xiàn)多繼承的效果即横。iOS代理模式的一個(gè)常見例子是郵件應(yīng)用噪生,郵件消息中收到的附件只會(huì)顯示一些基本信息,比如文件名和大小东囚。當(dāng)用戶點(diǎn)擊占位圖像跺嗽,開始加載附件的內(nèi)容時(shí),圖標(biāo)會(huì)替換為一個(gè)小進(jìn)度視圖页藻,表示實(shí)際加載進(jìn)度桨嫁。如果用戶不點(diǎn)擊占位圖標(biāo),附件就永遠(yuǎn)不會(huì)加載份帐。這不僅節(jié)省了忘了資源璃吧,也節(jié)省了內(nèi)存和郵件應(yīng)用運(yùn)行時(shí)的等待時(shí)間。
在iOS開發(fā)中废境,總是要關(guān)注內(nèi)存的使用量畜挨,所以出于性能考慮筒繁,推薦懶加載技術(shù)。通過使用代理模式巴元,對(duì)開銷大的數(shù)據(jù)實(shí)施懶加載毡咏,如文件系統(tǒng)中的大圖像文件或通過低速網(wǎng)絡(luò)從服務(wù)器下載的大型數(shù)據(jù)。如果大開銷的對(duì)象在收到請(qǐng)求之前不需要加載逮刨,則可通過虛擬代理向客戶端提供某些輕量的信息呕缭。(就是懶加載或輕量加載)
至于代理所在的應(yīng)用場景,就是上面所說的四種代理:遠(yuǎn)程代理修己,虛擬代理恢总,保護(hù)代理,智能引用代理箩退,這邊要根據(jù)具體需求去選擇离熏。