注:本博文來作者的其他博客GeekerProbe,但是均為原創(chuàng),要獲得最佳閱讀效果請移步至GeekerProbe。
在網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)過程中,需要針對客戶的行業(yè)特點(diǎn)、產(chǎn)品特性、目標(biāo)受眾和市場情況進(jìn)行定位分析,以確定網(wǎng)站的風(fēng)格、色彩、版式、交互等方面的設(shè)計(jì)方向。成都創(chuàng)新互聯(lián)還需要根據(jù)客戶的需求進(jìn)行功能模塊的開發(fā)和設(shè)計(jì),包括內(nèi)容管理、前臺(tái)展示、用戶權(quán)限管理、數(shù)據(jù)統(tǒng)計(jì)和安全保護(hù)等功能。本學(xué)期開了一門課程叫做《軟件體系結(jié)構(gòu)》,講的主要是設(shè)計(jì)模式的東西,而我在之前也看過設(shè)計(jì)模式的書,正好借此機(jī)會(huì)來整理一下自己所學(xué)到的知識(shí),因?yàn)樽约涸谧?code>iOS開發(fā),所以基本上這23種設(shè)計(jì)模式我都通過objective-C
來實(shí)現(xiàn)了。此系列文章的類圖都是來自《設(shè)計(jì)模式之禪》,有興趣的同學(xué)可以去買這本書看。
話說,在編碼編到一定的程度以后,由于代碼體系的龐大,結(jié)構(gòu)的復(fù)雜,自然就會(huì)上升到設(shè)計(jì)模式高度,而現(xiàn)在的軟件設(shè)計(jì)又基本都是面向?qū)ο蟮?,所以有了設(shè)計(jì)模式作支持,可以使軟件更加的穩(wěn)定安全,也更易于維護(hù)與拓展。
首先來介紹最常用最簡單的單例模式(Singleton),在以后的文章中再依次介紹其他的模式。
Ensure a class has only one instance, and provide a global point of access to it. (確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。)
單例模式確保在一個(gè)應(yīng)用中只產(chǎn)生一個(gè)實(shí)例,這是很有必要的,因?yàn)樵谖覀冏鲕浖O(shè)計(jì)的時(shí)候,有很多對象都是只需要一個(gè)就可以了,而不需要?jiǎng)?chuàng)建眾多的對象,這樣最顯而易見的就是節(jié)省了內(nèi)存空間。而且避免了這個(gè)類的頻繁的初始化與銷毀。有時(shí)為了實(shí)現(xiàn)某一種功能與操作而創(chuàng)建的類(工具類)往往也不需要多個(gè)對象,使用單例模式再合適不過。再延伸一點(diǎn),有時(shí)為了節(jié)省內(nèi)存對一個(gè)對象進(jìn)行復(fù)用的話也可以通過單例來實(shí)現(xiàn),這在手機(jī)軟件的開發(fā)中用得比較多,因?yàn)槭謾C(jī)的內(nèi)存實(shí)在是少得可憐。
正如前面說的,單例模式在內(nèi)存中只有一個(gè)實(shí)例,減少了內(nèi)存開支。特別是一個(gè)對象需要頻繁的創(chuàng)建、銷毀時(shí),而創(chuàng)建與銷毀的性能有無法優(yōu)化,單例模式的優(yōu)勢就非常明顯。
單例模式只生成一個(gè)實(shí)例,減少了系統(tǒng)性能開銷,當(dāng)一個(gè)對象的產(chǎn)生需要比較多的資源時(shí),如讀取配置、產(chǎn)生其他依賴對象時(shí),則可以通過在應(yīng)用啟動(dòng)時(shí)直接產(chǎn)生一個(gè)單例對象,然后永久駐留內(nèi)存的方式來解決。
單例模式可以避免對資源的多重占用。
單例模式可以在系統(tǒng)設(shè)置全局的訪問點(diǎn),優(yōu)化和共享資源訪問。
單例模式一般沒有接口,擴(kuò)展很困難,除了修改代碼基本上沒有第二種途徑實(shí)現(xiàn)。
單例模式對測試是不利的。在并行開發(fā)環(huán)境中,如果單例模式?jīng)]有完成,是不能進(jìn)行測試的。
單例模式與單一職責(zé)原則有沖突。
單例模式在iOS
開發(fā)中的使用還是蠻多的,許多Foundation
、Cocoa
和UIKit
中的類都實(shí)現(xiàn)了單例模式,比如應(yīng)用程序本身UIApplication
、文件操作類NSFileManager
、消息中心NSNotificitonCenter
等系統(tǒng)都已經(jīng)給我們實(shí)現(xiàn)單例,我們只需要使用就好了。在iOS
中使用單例模式要使用類方法,通過類方法返回該類的唯一對象。
我知道的在iOS
開發(fā)中實(shí)現(xiàn)單例模式主要有以下三種方式:
該方法是蘋果的官方文檔中寫的一種方式,通過覆蓋NSObject
的部分方法實(shí)現(xiàn),使該類無法alloc
、retain
、release
。這是最麻煩的一種方法,也是最不好的一種方法。
static Singleton *instance = nil; + (Singleton *)sharedInstance { if (instance == nil) { instance = [[super allocWithZone:NULL] init]; } return instance; } + (id)allocWithZone:(NSZone *)zone { return [[self sharedInstance] retain]; } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (NSUInteger)retainCount { return NSUIntegerMax; //denotes an object that cannot be released } - (void)release { //do nothing } - (id)autorelease { return self; }
可以看到這種方式,使用靜態(tài)成員維持了一個(gè)永久存在的對象,而且覆蓋了alloc
方法(alloc
方法會(huì)調(diào)用allocWithZone:
方法),并且也覆蓋了所有與引用技術(shù)有關(guān)的方法,這都使這個(gè)對象不會(huì)被銷毀。這樣看上去基本實(shí)現(xiàn)了我們需要的,但是寫起來麻煩不說,還有很大的一個(gè)問題,那就是多線程問題,如果是在多線程中那么該種方法就不能保證只產(chǎn)生一個(gè)對象了。所以這種方式只是介紹一下,并不推薦使用。
第二種跟第一種差不多,也是通過覆蓋NSObject
的方法實(shí)現(xiàn)的,但是它在第一種的基礎(chǔ)上增加了多線程的處理,所以即使在多線程下,該種方法創(chuàng)建的對象也是唯一的。這種方法已經(jīng)有大牛為我們寫好了,全都都是通過C
的宏定義#define
出來了?,F(xiàn)給出該頭文件的下載地址:
SynthesizeSingleton.h
使用時(shí)也非常方便,該頭文件也已給出使用方法,在這里我在說一下,供那些E文不好的同學(xué)使用。
使用這種方式首先把該頭文件加到我們的項(xiàng)目中,然后直接使用就可以了:
#import#import "SynthesizeSingleton.h" @interface Singleton : NSObject SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(Singleton); //定義該類的屬性,方法等 @end
@implementation Singleton SYNTHESIZE_SINGLETON_FOR_CLASS(Singleton); //屬性方法的實(shí)現(xiàn) @end
如此一來在使用時(shí),通過[Singleton sharedInstance]
就可以獲得該類的單例對象了。這種方法由于有了這個(gè)頭文件的支持,所以使得使用單例方便多了,而且也避免了多線程的問題。
這是最后一種也是我最推薦的一種。iOS
在4.0以后推出了block
和GCD
,這兩個(gè)特性給iOS
開發(fā)帶來的很大的便利,也使開發(fā)變得更加趣味話。那么如何通過GCD
+block
來實(shí)現(xiàn)單例模式呢,這主要?dú)w功于dispatch_once(dispatch_once_t *predicate, ^(void)block)
這個(gè)GCD
的函數(shù),他有兩個(gè)參數(shù)第一參數(shù)是一個(gè)指向dispatch_once_t
類型結(jié)構(gòu)體的指針,用來測試block
是否執(zhí)行完成,該指針?biāo)赶虻慕Y(jié)構(gòu)體必須是全局的或者靜態(tài)的,第二個(gè)參數(shù)是一個(gè)返回值與參數(shù)均為空的block
,在block
體中進(jìn)行對象的初始化即可。dispatch_once
在程序的生命周期中保證只會(huì)被調(diào)用一次,所以在多線程中也不會(huì)有問題。該種方法使用方法:
+ (Singleton *)sharedInstance { static Singleton *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[Singleton alloc]init]; }); return instance; }
使用該種方法只需要這簡單的幾句代碼就可以實(shí)現(xiàn)單例了。使用起來非常方便,但是這種創(chuàng)建單例的方法也不是完美的,它并不能阻止人們通過alloc
方法來實(shí)例化一個(gè)對象,所以這并不是嚴(yán)格意義上的單例模式,但是一般程序都是我們自己寫,我們自己記得就好了,這也沒什么可擔(dān)心的,從這一點(diǎn)上來說第二種方法又是比較好的,具體使用的時(shí)候呢,根據(jù)實(shí)際情況來吧,各取所需就好了。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。