iOS 原型模式

原型模式是非常簡(jiǎn)單的一種設(shè)計(jì)模式, 在多數(shù)情況下可被理解為一種深復(fù)制的行為穗熬。在Objective-C中使用原型模式, 首先要遵循NSCoping協(xié)議(OC中一些內(nèi)置類遵循該協(xié)議, 例如NSArray, NSMutableArray等)瞬雹。剛才我們提到了深復(fù)制, 一圖以蔽之:

Two kinds of Copy

深復(fù)制就是開辟新內(nèi)存實(shí)現(xiàn)真正的內(nèi)存復(fù)制, 淺復(fù)制, 只復(fù)制指針, 堆內(nèi)存不變. 在我們?cè)O(shè)計(jì)系統(tǒng)時(shí), 有時(shí)一些對(duì)象需要根據(jù)用戶操作完成拷貝備份等操作, 這時(shí)候, 如果再去按照原來的方法初始化一遍對(duì)象就會(huì)帶來一些不便和問題:

  1. 該對(duì)象的某些屬性是在用戶操作過程中產(chǎn)生的, 不能夠僅憑一個(gè)initXXX方法賦值;
  2. 常規(guī)賦值太過麻煩, 而且破壞封裝.

這時(shí)候原型模式的優(yōu)勢(shì)便體現(xiàn)出來了惕艳』嬷ぃ總結(jié)下原型模式的使用情況:

  1. 需要?jiǎng)?chuàng)建的對(duì)象應(yīng)獨(dú)立于其類型與創(chuàng)建方式仅炊。也就是說我們想要的對(duì)象并不能夠直接通過初始化函數(shù)來創(chuàng)建出來弄诲,其創(chuàng)建過程不具有普遍性且復(fù)雜寓涨。
  2. 要實(shí)例化類是在運(yùn)行時(shí)決定的盯串。在編寫代碼的時(shí)候并不知道哪種對(duì)象會(huì)被創(chuàng)建出來,其內(nèi)部的結(jié)構(gòu)如何復(fù)雜(例如:復(fù)雜程度取決于用戶的操作)戒良。
  3. 不想要與產(chǎn)品層次相對(duì)應(yīng)的工廠層次体捏。不通過工廠方法或者抽象工廠來控制產(chǎn)品的創(chuàng)建過程,想要直接復(fù)制對(duì)象
  4. 不同類的實(shí)例間的差異僅是狀態(tài)的若干組合蔬墩。因此復(fù)制相應(yīng)數(shù)量的原型比手工實(shí)例化更加方便译打。
  5. 類不容易創(chuàng)建,比如每個(gè)組件可把其他組件作為子節(jié)點(diǎn)的組合對(duì)象拇颅。復(fù)制已有的組合對(duì)象并對(duì)副本進(jìn)行修改會(huì)更加容易奏司。如果內(nèi)部結(jié)構(gòu)復(fù)雜,不容易重現(xiàn)樟插。

常見的使用場(chǎng)景 : 結(jié)構(gòu)復(fù)雜的類型, 例如《編程之道》中提及的Mark類型韵洋; 或者是相似類, 結(jié)構(gòu)一致, 但是屬性不同.

Demo

首先創(chuàng)建一個(gè)Player類, 擁有2個(gè)屬性highestLevel和currentLevel, 同時(shí)提供2個(gè)public方法修改這2個(gè)屬性. 代碼如下:

@interface Player : NSObject <NSCopying>
/**
 *  update player's current level during game
 *
 *  @param level
 */
- (void)updateCurrentLevel:(NSInteger)level;


/**
 *  update player's highest level during game
 *
 *  @param level
 */
- (void)updateHighestLevel:(NSInteger)level;

@end

最為關(guān)鍵的是Player需要實(shí)現(xiàn)NSCopying協(xié)議:

#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
{
    Player *copyPlayer = [[[self class] allocWithZone:zone] init];
    copyPlayer.highestLevel = self.highestLevel;
    copyPlayer.currentLevel = self.currentLevel;

    return copyPlayer;
}

這里大家看到NSZone類型, 這是個(gè)什么類型呢? 其實(shí)它是一個(gè)結(jié)構(gòu)體, 是為了防止內(nèi)存碎片化而引入的一個(gè)結(jié)構(gòu). NSZone會(huì)根據(jù)你想要開辟的內(nèi)存大小來分配內(nèi)存, 提高內(nèi)存管理. 然而官方的Programming with ARC Release Note也指出, 目前的runtime系統(tǒng)忽略了區(qū)域的概念黄锤,因?yàn)楸旧淼膬?nèi)存管理已經(jīng)非常有效率搪缨,使用Zone反而會(huì)降低內(nèi)存使用,訪問效率, 增加源代碼復(fù)雜度等.所以一般不使用NSZone鸵熟, 而在這個(gè)例子中副编, 雖說使用了allocWithZone的方法, 但是我們進(jìn)去看源代碼則會(huì)發(fā)現(xiàn): Apple其實(shí)還是用一般的初始化方法代替了原來的Zone開辟:

#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object         
  initializers instead"); 

原型設(shè)計(jì)模式基本就是這些, 當(dāng)然我們的Player類可以變成一個(gè)接口, 讓子類去實(shí)現(xiàn), 更好的體現(xiàn)面向接口編程.

結(jié)果

2015-09-18 21:30:32.072 DP_Prototype[1173:280693] <Player: 0x14d513f60>
2015-09-18 21:30:32.073 DP_Prototype[1173:280693] <Player: 0x14d5337e0>

在其他文件調(diào)用copy方法, 即可看到系統(tǒng)為我們新開辟的一塊內(nèi)存, 引用計(jì)數(shù)為1.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市流强,隨后出現(xiàn)的幾起案子痹届,更是在濱河造成了極大的恐慌,老刑警劉巖打月,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件队腐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡奏篙,警方通過查閱死者的電腦和手機(jī)柴淘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人为严,你說我怎么就攤上這事敛熬。” “怎么了第股?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵荸型,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我炸茧,道長(zhǎng),這世上最難降的妖魔是什么稿静? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任梭冠,我火速辦了婚禮,結(jié)果婚禮上改备,老公的妹妹穿的比我還像新娘控漠。我一直安慰自己,他們只是感情好悬钳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布盐捷。 她就那樣靜靜地躺著,像睡著了一般默勾。 火紅的嫁衣襯著肌膚如雪碉渡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天母剥,我揣著相機(jī)與錄音滞诺,去河邊找鬼。 笑死环疼,一個(gè)胖子當(dāng)著我的面吹牛习霹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炫隶,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淋叶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了伪阶?” 一聲冷哼從身側(cè)響起煞檩,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎望门,沒想到半個(gè)月后形娇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筹误,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年桐早,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哄酝,死狀恐怖友存,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陶衅,我是刑警寧澤屡立,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站搀军,受9級(jí)特大地震影響膨俐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罩句,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一焚刺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧门烂,春花似錦乳愉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至慨丐,卻和暖如春坡脐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背房揭。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工挨措, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人崩溪。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓浅役,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親伶唯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子觉既,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • 原型模式copy()、NSCopying協(xié)議數(shù)組乳幸、字典瞪讼、集合中的元素也要可以復(fù)制,即實(shí)現(xiàn)NSCopy協(xié)議粹断,否則崩潰...
    印林泉閱讀 397評(píng)論 0 1
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,140評(píng)論 30 470
  • 1大同小異的工作周報(bào) Sunny軟件公司一直使用自行開發(fā)的一套OA (Office Automatic符欠,辦公自動(dòng)化...
    justCode_閱讀 1,156評(píng)論 0 3
  • 1 場(chǎng)景問題# 1.1 訂單處理系統(tǒng)## 考慮這樣一個(gè)實(shí)際應(yīng)用:訂單處理系統(tǒng)。 現(xiàn)在有一個(gè)訂單處理的系統(tǒng)瓶埋,里面有個(gè)...
    七寸知架構(gòu)閱讀 4,425評(píng)論 3 63
  • 設(shè)計(jì)模式匯總 一希柿、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用诊沪、多...
    MinoyJet閱讀 3,944評(píng)論 1 15