ps怎么做網(wǎng)站橫幅廣告長沙h5網(wǎng)站建設(shè)
一、單實例模式
在設(shè)計模式中,單實例模式幾乎是所有語言中都非常常用的一種設(shè)計模式。它在實際的應(yīng)用中也非常廣泛,在很多的開源框架中,都可以看到單實例的影子。單實例,簡單的就可以看做在整個應(yīng)用周期中,只有一個對象的變量。其好處其實就一點,可以集中控制對對象的各種處理(比如優(yōu)化、內(nèi)存管理等等),缺點其實就是兩個,一個是生命周期無法動態(tài)控制;另外一個就是無法動態(tài)伸縮。前者容易理解,后者舉個簡單例子,如果想同時連接多個數(shù)據(jù)庫,這就不好控制了。
二、靜態(tài)方法和靜態(tài)變量
學(xué)習(xí)C/C++語言的,對靜態(tài)變量和靜態(tài)方法都是很熟悉的。靜態(tài)化和單實例也有著千絲萬縷的關(guān)系,在實現(xiàn)單實例的發(fā)展過程中,有很多種方式,現(xiàn)在比較常見的基本就是兩種,一種是使用函數(shù)的局部靜態(tài)變量,一種是使用std::call_once,而且這兩個都需要從C++0x開始支持。
首先說明一點,此處不是分析如何實現(xiàn)單實例,所以不會對實現(xiàn)的各種方式進(jìn)行分析說明,重點在于單實例與靜態(tài)化的關(guān)系這一點進(jìn)行深入剖析。為什么單實例中對靜態(tài)化情有獨鐘呢?可不可以全部使用靜態(tài)化來實現(xiàn)單實例呢?
答案其實反復(fù)回答過,靜態(tài)變量可以防止反復(fù)檢測(比如經(jīng)典的Double Check)的性能損失(函數(shù)的局部靜態(tài)變量仍然會有一個檢測過程,性能仍然會有些損失),至于能不能使用全部靜態(tài)化來實現(xiàn)單實例,當(dāng)然是沒有問題的。但問題在于,使用這種方式,會喪失一定的靈活性,這個在下面分進(jìn)行分析。
三、單實例中的靜態(tài)化
那么單實例中使用靜態(tài)化操作有什么優(yōu)勢呢?
1、線程安全性
熟悉全局和靜態(tài)變量的開發(fā)者都有一個頭疼的地方,編譯器是無法保證多個文件內(nèi)的相關(guān)這樣的變量的初始化順序的。這就出現(xiàn)一個非常難受的問題,如果以后擴展需要多個文件(或者多個庫)內(nèi)的全局或者靜態(tài)變量需要互相依賴,有可能會出一些讓人想象不到的問題。有大牛提出過,把全局或者靜態(tài)變量搞到一個文件中,可實際場景中,算法保密甚至第三方庫都使開發(fā)者無法達(dá)到這樣的目的。
而Meyers’ Singleton即Scott Meyers最早提出來的C++單例模式的寫法,其實就是局部靜態(tài)變量的方式來實現(xiàn),不過在前面也提到了,它需要C++0x做保證,同樣,在一些編譯器上,可能也有一些具體的問題,但這不是討論的范疇了。
2、接口繼承
如果使用單實例封裝使用靜態(tài)化,那么就可以實現(xiàn)繼承來延續(xù)靜態(tài)化的應(yīng)用。這其實是一個非常重要的應(yīng)用,可以繼承,意味著可擴展性極大的增強,即靈活性的增加。
3、延遲加載
所謂延遲加載,其實就是懶漢模式,它只會在第一次用到時創(chuàng)建這個對象。這在一些資源要求嚴(yán)格的場景下,還是很有用處的。
4、解決了多文件(庫)的互相引用問題
其實這點還是靜態(tài)變量的初始化順序?qū)е碌膯栴},這個非常重要,可能很多人都沒遇到過,但經(jīng)驗表明,一旦出現(xiàn)這個問題,簡直就是一場災(zāi)難,因為正常的思維情況下很少考慮這種情況。當(dāng)你弄明白是這個原因后,會陷入無比的自責(zé)和自餒中。
5、生命周期
單實例封裝靜化,可以主動控制生命周期,這與使用一個單純的靜態(tài)或者全局變量有著可控的優(yōu)勢。畢竟全局(靜態(tài))變量一旦生成,就是整個進(jìn)程的生命周期陪伴著,這對于一些對資源要求苛刻的場景下,還是很在裨益的。
另外,單實例的參數(shù)傳遞(非常大的應(yīng)用程序中)以及后期對測試的支持,都可以做為一種優(yōu)勢來進(jìn)行說明。但重點是靜態(tài)化使用與單實例中,如何最具有優(yōu)勢,這才是開發(fā)者需要首先考慮的。
下面給出一個Meyers’ Singleton例子:
struct Singleton
{static Singleton &instance(){static Singleton s;return s;} // instanceSingleton(const Singleton &) = delete;Singleton & operator = (const Singleton &) = delete;private:Singleton() {}~Singleton() {}}; // struct Singleton
struct OwnerSingleton:public Singleton
{};
不過一般來說,可能對絕大多數(shù)程序員來說,實際情況中遇到單例繼承的情況極為罕見吧。
其實直接使用全局或者靜態(tài)變量與使用單實例,從開發(fā)的本質(zhì)來說,區(qū)別不大,但單實例更好的解決了在上層邏輯上的靈活擴展性,這其實就是設(shè)計的意義,也是設(shè)計模式的意義。實現(xiàn)功能可能大家都會,可如何做得更好,就見仁見智了。
四、總結(jié)
到最后,總結(jié)各種經(jīng)驗其實可以發(fā)現(xiàn),在實際的應(yīng)用場景上,使用一些習(xí)慣用法或者說設(shè)計模式的目的,主要是為了擴展性和防御性編程。如果能夠明確的知道不會發(fā)生或者某些異常會被阻止的情況下,不進(jìn)行使用其實也是沒問題的(話只能說到這兒,大家自己考慮)。說這些話的目的就是,經(jīng)驗是個好東西,但不要陷入經(jīng)驗主義,書本是個好東西,不要陷入本本主義。實踐是檢驗真理的唯一標(biāo)準(zhǔn),抓住老鼠的一定是好貓。