在iOS中理解設(shè)計模式

設(shè)計模式即編碼的工程化,是代碼設(shè)計經(jīng)驗的總結(jié)。使用設(shè)計模式可提高代碼的復(fù)用性、可讀性和可靠性。設(shè)計模式在各類面向?qū)ο蟮恼Z言中基本相通,僅在具體的實現(xiàn)語法上略有差異,下面我們以O(shè)C為例來理解和研究一些常用的設(shè)計模式。


單例模式

保證程序運行中,一個類全局只有一個實例。它提供了對類對象的全局訪問點,在整個過程中共享著一份資源。

應(yīng)用:登錄控制體系、網(wǎng)絡(luò)請求、音樂播放、分享體系等。

+ (instancetype)sharedInstance {

? ? ? static Singleton *singleton = nil;

? ? ? static dispatch_once_t onceToken;

? ? ? dispatch_once(&onceToken, ^{

? ? ? ? ? ? singleton = [[Singleton alloc] init];

? ? ? });

? ? ? return singleton;?

}

//嚴(yán)謹(jǐn)情況下應(yīng)把copyWithZone和mutableCopyWithZone也重寫

注:可將allocWithZone重寫為dispatch_once實現(xiàn)單例,sharedInstance中調(diào)用默認(rèn)的alloc init(alloc會默認(rèn)調(diào)用allocWithZone),此時,單例可被繼承,重寫init方法實現(xiàn)子單例的擴(kuò)展。如下:

static Singleton *_instance;

+ (id)allocWithZone:(struct _NSZone *)zone {

? ? ? static dispatch_once_t onceToken;

? ? ? dispatch_once(&onceToken, ^{

? ? ? ? ? ? _instance = [super allocWithZone:zone];

? ? ? )};

? ? ? return _instance;

}

+ (instancetype)sharedInstance {

? ? ? ?if(!_instance) {

? ? ? ? ? ? ?_instance = [[Singleton alloc] init];

? ? ? ? }

? ? ? ? return _instance;

}

使用帶參數(shù)的宏定義可以把單例模式的聲明優(yōu)化到只寫一次,在各單例類中的.h、.m中只需調(diào)用宏定義即可。

最后補(bǔ)充一下iOS系統(tǒng)的單例類:UIApplication,UIScreen,NSNotificationCenter,NSFileManager,NSUserDefaults,NSURLCache,NSHTTPCookieStorage等。

工廠模式

簡單工廠模式

一個工廠類,根據(jù)傳入?yún)?shù)不同,決定初始化某個具體產(chǎn)品實例。

應(yīng)用理解:一個簡單四則運算計算器。如果不使用工廠模式,要實現(xiàn)加減乘除四個方法就需要new4個運算方法類,這顯然不是一個完美的解決方案。此時,若有個產(chǎn)品基類BaseCalculate,它包括加減乘除四個產(chǎn)品類(Add,Minus,Multiply,Devide),在需要實例化運算對象的地方,使用運算工廠類CalcuteFactory,根據(jù)類型返回產(chǎn)品類的方法-(BaseCaculate *)createWithType:(id)type;生成對應(yīng)運算的產(chǎn)品類對象。

簡單工廠模式

缺點:增加或者修改產(chǎn)品類時,需在代碼層次修改工廠類(此時需重新測試工廠類),不夠靈活,不便擴(kuò)展。

為解決上述缺點,出現(xiàn)了第二種工廠模式:

工廠方法模式

一個工廠類,一個產(chǎn)品類對應(yīng)一個工廠子類(產(chǎn)品與工廠配套),即,擴(kuò)展產(chǎn)品類別時需同時擴(kuò)展工廠子類,與簡單工廠模式相比,抽象了工廠類。工廠子類中重寫抽象工廠類中的方法生產(chǎn)對應(yīng)的產(chǎn)品子類。

工廠方法模式

缺點顯而易見:大量的產(chǎn)品+工廠類,且產(chǎn)品和工廠間隔斷嚴(yán)重?zé)o法復(fù)用相同代碼。

于是抽象工廠模式應(yīng)運而生:

抽象工廠模式

抽象工廠模式的最大特點就是有多個抽象產(chǎn)品類。找出某類產(chǎn)品的共性,設(shè)計出此類產(chǎn)品的抽象類(派生出多個具體產(chǎn)品類)。而其具有一個抽象工廠類和多個具體工廠類,每個具體工廠類都可創(chuàng)建多個具體產(chǎn)品類。

抽象工廠模式

觀察者模式

發(fā)布(publish)- 訂閱(Subscribe)模式,用于一對多依賴關(guān)系中的解耦。對象可以通過注冊,成為觀察者(Observer),去訂閱中心對象(Subject)的變化。Subject(被觀察者)則需要實現(xiàn)觀察者注冊、數(shù)據(jù)更新通知、觀察者移除三個基礎(chǔ)方法。

NSNotification

注冊觀察者

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notice:) name:@"PostName" object:nil];

- (void)notice:(id)sender { NSLog(@"%@",sender); }

被觀察者發(fā)出通知

[[NSNotificationCenterdefaultCenter] postNotificationName:@"PostName" object:nil];

移除通知

- (void)dealloc ?{

? ? ? [[NSNotificationCenter defaultCenter] removeObserver:self name:@"PostName" object:nil];

}

KVO

KVC、KVO小結(jié)和應(yīng)用


代理模式

OC和Swift中的protocol

非正式協(xié)議

即Category,如NSString (StringFrame)。

代理與Block

1、block是讓代碼塊以閉包(一個函數(shù)+其執(zhí)行的外部上下文變量)的形式傳遞內(nèi)容,實在是太輕量級了,適用于大多數(shù)異步和簡單的回調(diào)。

2、當(dāng)有多個方法回調(diào)時應(yīng)當(dāng)選用delegate會更清晰,如UITableView的delegate代理方法。

3、block會涉及到棧區(qū)到堆區(qū)的拷貝等操作,delegate只是定義了一個方法列表,在遵守了協(xié)議的對象的objc_protocol_list中添加了一個節(jié)點,運行時向?qū)ο蟀l(fā)送消息即可。所以block在時間空間消耗都大于delegate,性能消耗較大。

4、代理更加面向過程,block更加面向結(jié)果。


策略模式

#結(jié)合現(xiàn)金支付計算策略實例詳細(xì)說明#

1、定義一個抽象的、通用的算法(抽象策略類BaseStrategy)協(xié)議,此角色給出所有具體策略類所需的接口;

@protocol CashBase?

-(CGFloat)acceptCash:(CGFloat)cash;

@end

2、讓每個具體算法(繼承Base的具體策略類NormalStrategy,SpecialStrategy)都遵循他的守則,提供了具體的算法實現(xiàn)了抽象策略類定義的接口;

@interface CashNormal : NSObject <CashBase>

@end

@implementation CashNormal

-(CGFloat)acceptCash:(CGFloat)cash { return cash; }

@end

@interface CaseReturn : NSObject <CashBase>

-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn;

@end

@implementation CaseReturn ? ??

-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn {

? ? ? if (self) {

? ? ? ? ? ?_moneyReturn = moneyReturn;

? ? ? }

? ? ? return self;

}

-(CGFloat)acceptCash:(CGFloat)cash {

? ? ? return cash - self.moneyReturn;

}

@end

3、然后需要定義一個環(huán)境角色(Context類)用來持有一個Strategy的引用,配合簡單工廠模式,根據(jù)入?yún)Q定調(diào)用哪個具體策略類算法;

@interface CashContext : NSObject

-(instancetype)initWithCashType:(CashType)type;

-(CGFloat)getResult:(CGFloat)money;

@end

@implementation CashContext

-(instancetype)initWithCashType:(CashType)type{

? ? ? //根據(jù)type初始化算法實例

}

-(CGFloat)getResult:(CGFloat)money{

? ? ? //算法實例調(diào)用策略接口

? ? ? return [self.cashSuper acceptCash:money];

}

@end

4、最后在需要的地方調(diào)用Context對象。

CashContext * context = [[CashContext alloc] initWithCashType:CashTypeNormal];

NSLog(@"結(jié)果是%f",[context getResult:100]);


裝飾模式

不修改原類代碼的情況下,動態(tài)、透明的給一個對象增加新的行為和職責(zé),Decorator比生成子類更加靈活,其目的是把功能分散,運行期間再動態(tài)組合。

裝飾器的構(gòu)成:1、Component,抽象的組件父類,聲明了一些方法由子類進(jìn)行重載;ConcreteComponent,具體的組件類,實現(xiàn)了組件接口,通常是被裝飾的原始對象。

2、Decorator,裝飾器父類(Component細(xì)化后的抽象類),用來持有原對象(被裝飾對象)。ConcreteDecorator具體的裝飾器類,具體實現(xiàn)要添加的功能,并內(nèi)嵌Component操作,以裝飾具體的組件對象。

在iOS中,分類(category)簡單便捷的實現(xiàn)了裝飾器設(shè)計模式所能達(dá)到的功能,但嚴(yán)格意義上講并不符合裝飾器模式的定義。

注:1、有些教程中說委托也是iOS中的一種裝飾器模式,但我認(rèn)為委托沒有做到裝飾模式定義中“不修改原類代碼”的要求;2、分類中定義的方法不要和原有類的方法重名。


軟件開發(fā)中還用很多常用的設(shè)計模式,如模板方法模式(提取算法可復(fù)用結(jié)構(gòu),延遲某些特定步驟到子類:如問答題的不變部分(題目)和變化部分(答案))、外觀模式(為一套需要同時調(diào)用的子系統(tǒng)定義一個高層的綜合接口,便于多個接口同時調(diào)用)、建造者模式、狀態(tài)模式、適配器模式、備忘錄模式、組合模式、迭代器模式、單列模式、橋接模式、命令模式、職責(zé)鏈模式、中介者模式、享元模式、解釋器模式、訪問者模式、原型模式(已有對象深拷貝申請新內(nèi)存,生成新對象,需滿足NSCopying協(xié)議)等。

最后提供一下容易亂入的MVC,MVVM等設(shè)計模式等鏈接,嚴(yán)格來說,它們應(yīng)稱為架構(gòu)設(shè)計模式,而非廣義上的編碼設(shè)計模式。

架構(gòu)設(shè)計模式之MVC和MVVM


寫在最后

沒有最后 <( ̄︶ ̄)>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計模式匯總 一、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,094評論 1 15
  • 一、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    RamboLI閱讀 833評論 0 1
  • 一、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    lichengjin閱讀 1,000評論 0 8
  • 原文鏈接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤獨雜貨鋪閱讀 1,639評論 0 3
  • 設(shè)計模式基本原則 開放-封閉原則(OCP),是說軟件實體(類、模塊、函數(shù)等等)應(yīng)該可以拓展,但是不可修改。開-閉原...
    西山薄涼閱讀 4,082評論 3 14

友情鏈接更多精彩內(nèi)容