隨筆-11  評(píng)論-0  文章-0  trackbacks-0
            2015年7月17日
               摘要: 設(shè)計(jì)模式的六大原則總原則:開(kāi)閉原則(Open Close Principle)開(kāi)閉原則就是說(shuō)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候,不能去修改原有的代碼,而是要擴(kuò)展原有代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好,易于維護(hù)和升級(jí)。想要達(dá)到這樣的效果,我們需要使用接口和抽象類等,后面的具體設(shè)計(jì)中我們會(huì)提到這點(diǎn)。1、單一職責(zé)原則不要存在多于一個(gè)導(dǎo)致類變更的原因,也就是...  閱讀全文
          posted @ 2015-07-21 16:44 wxb1988 閱讀(213) | 評(píng)論 (0)編輯 收藏
          定義:為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無(wú)需指定他們的具體類。

          類型:創(chuàng)建類模式

          類圖:

          抽象工廠模式與工廠方法模式的區(qū)別

                  抽象工廠模式是工廠方法模式的升級(jí)版本,他用來(lái)創(chuàng)建一組相關(guān)或者相互依賴的對(duì)象。他與工廠方法模式的區(qū)別就在于,工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu);而抽象工廠模式則是針對(duì)的多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)。在編程中,通常一個(gè)產(chǎn)品結(jié)構(gòu),表現(xiàn)為一個(gè)接口或者抽象類,也就是說(shuō),工廠方法模式提供的所有產(chǎn)品都是衍生自同一個(gè)接口或抽象類,而抽象工廠模式所提供的產(chǎn)品則是衍生自不同的接口或抽象類。

                  在抽象工廠模式中,有一個(gè)產(chǎn)品族的概念:所謂的產(chǎn)品族,是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中功能相關(guān)聯(lián)的產(chǎn)品組成的家族。抽象工廠模式所提供的一系列產(chǎn)品就組成一個(gè)產(chǎn)品族;而工廠方法提供的一系列產(chǎn)品稱為一個(gè)等級(jí)結(jié)構(gòu)。我們依然拿生產(chǎn)汽車的例子來(lái)說(shuō)明他們之間的區(qū)別。

                  在上面的類圖中,兩廂車和三廂車稱為兩個(gè)不同的等級(jí)結(jié)構(gòu);而2.0排量車和2.4排量車則稱為兩個(gè)不同的產(chǎn)品族。再具體一點(diǎn),2.0排量?jī)蓭嚭?.4排量?jī)蓭噷儆谕粋€(gè)等級(jí)結(jié)構(gòu),2.0排量三廂車和2.4排量三廂車屬于另一個(gè)等級(jí)結(jié)構(gòu);而2.0排量?jī)蓭嚭?.0排量三廂車屬于同一個(gè)產(chǎn)品族,2.4排量?jī)蓭嚭?.4排量三廂車屬于另一個(gè)產(chǎn)品族。

                  明白了等級(jí)結(jié)構(gòu)和產(chǎn)品族的概念,就理解工廠方法模式和抽象工廠模式的區(qū)別了,如果工廠的產(chǎn)品全部屬于同一個(gè)等級(jí)結(jié)構(gòu),則屬于工廠方法模式;如果工廠的產(chǎn)品來(lái)自多個(gè)等級(jí)結(jié)構(gòu),則屬于抽象工廠模式。在本例中,如果一個(gè)工廠模式提供2.0排量?jī)蓭嚭?.4排量?jī)蓭嚕敲此麑儆诠S方法模式;如果一個(gè)工廠模式是提供2.4排量?jī)蓭嚭?.4排量三廂車兩個(gè)產(chǎn)品,那么這個(gè)工廠模式就是抽象工廠模式,因?yàn)樗峁┑漠a(chǎn)品是分屬兩個(gè)不同的等級(jí)結(jié)構(gòu)。當(dāng)然,如果一個(gè)工廠提供全部四種車型的產(chǎn)品,因?yàn)楫a(chǎn)品分屬兩個(gè)等級(jí)結(jié)構(gòu),他當(dāng)然也屬于抽象工廠模式了。

          抽象工廠模式代碼

          1. interface IProduct1 {  
          2.     public void show();  
          3. }  
          4. interface IProduct2 {  
          5.     public void show();  
          6. }  
          7.   
          8. class Product1 implements IProduct1 {  
          9.     public void show() {  
          10.         System.out.println("這是1型產(chǎn)品");  
          11.     }  
          12. }  
          13. class Product2 implements IProduct2 {  
          14.     public void show() {  
          15.         System.out.println("這是2型產(chǎn)品");  
          16.     }  
          17. }  
          18.   
          19. interface IFactory {  
          20.     public IProduct1 createProduct1();  
          21.     public IProduct2 createProduct2();  
          22. }  
          23. class Factory implements IFactory{  
          24.     public IProduct1 createProduct1() {  
          25.         return new Product1();  
          26.     }  
          27.     public IProduct2 createProduct2() {  
          28.         return new Product2();  
          29.     }  
          30. }  
          31.   
          32. public class Client {  
          33.     public static void main(String[] args){  
          34.         IFactory factory = new Factory();  
          35.         factory.createProduct1().show();  
          36.         factory.createProduct2().show();  
          37.     }  
          38. }  

          抽象工廠模式的優(yōu)點(diǎn)

                  抽象工廠模式除了具有工廠方法模式的優(yōu)點(diǎn)外,最主要的優(yōu)點(diǎn)就是可以在類的內(nèi)部對(duì)產(chǎn)品族進(jìn)行約束。所謂的產(chǎn)品族,一般或多或少的都存在一定的關(guān)聯(lián),抽象工廠模式就可以在類內(nèi)部對(duì)產(chǎn)品族的關(guān)聯(lián)關(guān)系進(jìn)行定義和描述,而不必專門引入一個(gè)新的類來(lái)進(jìn)行管理。

           

          抽象工廠模式的缺點(diǎn)

                 產(chǎn)品族的擴(kuò)展將是一件十分費(fèi)力的事情,假如產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品,則幾乎所有的工廠類都需要進(jìn)行修改。所以使用抽象工廠模式時(shí),對(duì)產(chǎn)品等級(jí)結(jié)構(gòu)的劃分是非常重要的。

           

          適用場(chǎng)景

                 當(dāng)需要?jiǎng)?chuàng)建的對(duì)象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時(shí),便可以使用抽象工廠模式。說(shuō)的更明白一點(diǎn),就是一個(gè)繼承體系中,如果存在著多個(gè)等級(jí)結(jié)構(gòu)(即存在著多個(gè)抽象類),并且分屬各個(gè)等級(jí)結(jié)構(gòu)中的實(shí)現(xiàn)類之間存在著一定的關(guān)聯(lián)或者約束,就可以使用抽象工廠模式。假如各個(gè)等級(jí)結(jié)構(gòu)中的實(shí)現(xiàn)類之間不存在關(guān)聯(lián)或約束,則使用多個(gè)獨(dú)立的工廠來(lái)對(duì)產(chǎn)品進(jìn)行創(chuàng)建,則更合適一點(diǎn)。

           

          總結(jié)

                 無(wú)論是簡(jiǎn)單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬于工廠模式,在形式和特點(diǎn)上也是極為相似的,他們的最終目的都是為了解耦。在使用時(shí),我們不必去在意這個(gè)模式到底工廠方法模式還是抽象工廠模式,因?yàn)樗麄冎g的演變常常是令人琢磨不透的。經(jīng)常你會(huì)發(fā)現(xiàn),明明使用的工廠方法模式,當(dāng)新需求來(lái)臨,稍加修改,加入了一個(gè)新方法后,由于類中的產(chǎn)品構(gòu)成了不同等級(jí)結(jié)構(gòu)中的產(chǎn)品族,它就變成抽象工廠模式了;而對(duì)于抽象工廠模式,當(dāng)減少一個(gè)方法使的提供的產(chǎn)品不再構(gòu)成產(chǎn)品族之后,它就演變成了工廠方法模式。

                 所以,在使用工廠模式時(shí),只需要關(guān)心降低耦合度的目的是否達(dá)到了。

          posted @ 2015-07-20 22:34 wxb1988 閱讀(196) | 評(píng)論 (0)編輯 收藏

          定義:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,工廠方法使一個(gè)類的實(shí)例化延遲到其子類。

          類型:創(chuàng)建類模式

          類圖:

          工廠方法模式代碼

          1. interface IProduct {  
          2.     public void productMethod();  
          3. }  
          4.   
          5. class Product implements IProduct {  
          6.     public void productMethod() {  
          7.         System.out.println("產(chǎn)品");  
          8.     }  
          9. }  
          10.   
          11. interface IFactory {  
          12.     public IProduct createProduct();  
          13. }  
          14.   
          15. class Factory implements IFactory {  
          16.     public IProduct createProduct() {  
          17.         return new Product();  
          18.     }  
          19. }  
          20.   
          21. public class Client {  
          22.     public static void main(String[] args) {  
          23.         IFactory factory = new Factory();  
          24.         IProduct prodect = factory.createProduct();  
          25.         prodect.productMethod();  
          26.     }  
          27. }  

          工廠模式:

                  首先需要說(shuō)一下工廠模式。工廠模式根據(jù)抽象程度的不同分為三種:簡(jiǎn)單工廠模式(也叫靜態(tài)工廠模式)、本文所講述的工廠方法模式、以及抽象工廠模式。工廠模式是編程中經(jīng)常用到的一種模式。它的主要優(yōu)點(diǎn)有:

          • 可以使代碼結(jié)構(gòu)清晰,有效地封裝變化。在編程中,產(chǎn)品類的實(shí)例化有時(shí)候是比較復(fù)雜和多變的,通過(guò)工廠模式,將產(chǎn)品的實(shí)例化封裝起來(lái),使得調(diào)用者根本無(wú)需關(guān)心產(chǎn)品的實(shí)例化過(guò)程,只需依賴工廠即可得到自己想要的產(chǎn)品。
          • 對(duì)調(diào)用者屏蔽具體的產(chǎn)品類。如果使用工廠模式,調(diào)用者只關(guān)心產(chǎn)品的接口就可以了,至于具體的實(shí)現(xiàn),調(diào)用者根本無(wú)需關(guān)心。即使變更了具體的實(shí)現(xiàn),對(duì)調(diào)用者來(lái)說(shuō)沒(méi)有任何影響。
          • 降低耦合度。產(chǎn)品類的實(shí)例化通常來(lái)說(shuō)是很復(fù)雜的,它需要依賴很多的類,而這些類對(duì)于調(diào)用者來(lái)說(shuō)根本無(wú)需知道,如果使用了工廠方法,我們需要做的僅僅是實(shí)例化好產(chǎn)品類,然后交給調(diào)用者使用。對(duì)調(diào)用者來(lái)說(shuō),產(chǎn)品所依賴的類都是透明的。

           

          工廠方法模式:

                 通過(guò)工廠方法模式的類圖可以看到,工廠方法模式有四個(gè)要素:

          • 工廠接口。工廠接口是工廠方法模式的核心,與調(diào)用者直接交互用來(lái)提供產(chǎn)品。在實(shí)際編程中,有時(shí)候也會(huì)使用一個(gè)抽象類來(lái)作為與調(diào)用者交互的接口,其本質(zhì)上是一樣的。
          • 工廠實(shí)現(xiàn)。在編程中,工廠實(shí)現(xiàn)決定如何實(shí)例化產(chǎn)品,是實(shí)現(xiàn)擴(kuò)展的途徑,需要有多少種產(chǎn)品,就需要有多少個(gè)具體的工廠實(shí)現(xiàn)。
          • 產(chǎn)品接口。產(chǎn)品接口的主要目的是定義產(chǎn)品的規(guī)范,所有的產(chǎn)品實(shí)現(xiàn)都必須遵循產(chǎn)品接口定義的規(guī)范。產(chǎn)品接口是調(diào)用者最為關(guān)心的,產(chǎn)品接口定義的優(yōu)劣直接決定了調(diào)用者代碼的穩(wěn)定性。同樣,產(chǎn)品接口也可以用抽象類來(lái)代替,但要注意最好不要違反里氏替換原則。
          • 產(chǎn)品實(shí)現(xiàn)。實(shí)現(xiàn)產(chǎn)品接口的具體類,決定了產(chǎn)品在客戶端中的具體行為。

                  前文提到的簡(jiǎn)單工廠模式跟工廠方法模式極為相似,區(qū)別是:簡(jiǎn)單工廠只有三個(gè)要素,他沒(méi)有工廠接口,并且得到產(chǎn)品的方法一般是靜態(tài)的。因?yàn)闆](méi)有工廠接口,所以在工廠實(shí)現(xiàn)的擴(kuò)展性方面稍弱,可以算所工廠方法模式的簡(jiǎn)化版,關(guān)于簡(jiǎn)單工廠模式,在此一筆帶過(guò)。

                

          適用場(chǎng)景:

                  不管是簡(jiǎn)單工廠模式,工廠方法模式還是抽象工廠模式,他們具有類似的特性,所以他們的適用場(chǎng)景也是類似的。

                  首先,作為一種創(chuàng)建類模式,在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠方法模式。有一點(diǎn)需要注意的地方就是復(fù)雜對(duì)象適合使用工廠模式,而簡(jiǎn)單對(duì)象,特別是只需要通過(guò)new就可以完成創(chuàng)建的對(duì)象,無(wú)需使用工廠模式。如果使用工廠模式,就需要引入一個(gè)工廠類,會(huì)增加系統(tǒng)的復(fù)雜度。

                 其次,工廠模式是一種典型的解耦模式,迪米特法則在工廠模式中表現(xiàn)的尤為明顯。假如調(diào)用者自己組裝產(chǎn)品需要增加依賴關(guān)系時(shí),可以考慮使用工廠模式。將會(huì)大大降低對(duì)象之間的耦合度。

                 再次,由于工廠模式是依靠抽象架構(gòu)的,它把實(shí)例化產(chǎn)品的任務(wù)交由實(shí)現(xiàn)類完成,擴(kuò)展性比較好。也就是說(shuō),當(dāng)需要系統(tǒng)有比較好的擴(kuò)展性時(shí),可以考慮工廠模式,不同的產(chǎn)品用不同的實(shí)現(xiàn)工廠來(lái)組裝。

                

          典型應(yīng)用

                 要說(shuō)明工廠模式的優(yōu)點(diǎn),可能沒(méi)有比組裝汽車更合適的例子了。場(chǎng)景是這樣的:汽車由發(fā)動(dòng)機(jī)、輪、底盤組成,現(xiàn)在需要組裝一輛車交給調(diào)用者。假如不使用工廠模式,代碼如下:

          1. class Engine {  
          2.     public void getStyle(){  
          3.         System.out.println("這是汽車的發(fā)動(dòng)機(jī)");  
          4.     }  
          5. }  
          6. class Underpan {  
          7.     public void getStyle(){  
          8.         System.out.println("這是汽車的底盤");  
          9.     }  
          10. }  
          11. class Wheel {  
          12.     public void getStyle(){  
          13.         System.out.println("這是汽車的輪胎");  
          14.     }  
          15. }  
          16. public class Client {  
          17.     public static void main(String[] args) {  
          18.         Engine engine = new Engine();  
          19.         Underpan underpan = new Underpan();  
          20.         Wheel wheel = new Wheel();  
          21.         ICar car = new Car(underpan, wheel, engine);  
          22.         car.show();  
          23.     }  
          24. }  


                  可以看到,調(diào)用者為了組裝汽車還需要另外實(shí)例化發(fā)動(dòng)機(jī)、底盤和輪胎,而這些汽車的組件是與調(diào)用者無(wú)關(guān)的,嚴(yán)重違反了迪米特法則,耦合度太高。并且非常不利于擴(kuò)展。另外,本例中發(fā)動(dòng)機(jī)、底盤和輪胎還是比較具體的,在實(shí)際應(yīng)用中,可能這些產(chǎn)品的組件也都是抽象的,調(diào)用者根本不知道怎樣組裝產(chǎn)品。假如使用工廠方法的話,整個(gè)架構(gòu)就顯得清晰了許多。

          1. interface IFactory {  
          2.     public ICar createCar();  
          3. }  
          4. class Factory implements IFactory {  
          5.     public ICar createCar() {  
          6.         Engine engine = new Engine();  
          7.         Underpan underpan = new Underpan();  
          8.         Wheel wheel = new Wheel();  
          9.         ICar car = new Car(underpan, wheel, engine);  
          10.         return car;  
          11.     }  
          12. }  
          13. public class Client {  
          14.     public static void main(String[] args) {  
          15.         IFactory factory = new Factory();  
          16.         ICar car = factory.createCar();  
          17.         car.show();  
          18.     }  
          19. }  

                  使用工廠方法后,調(diào)用端的耦合度大大降低了。并且對(duì)于工廠來(lái)說(shuō),是可以擴(kuò)展的,以后如果想組裝其他的汽車,只需要再增加一個(gè)工廠類的實(shí)現(xiàn)就可以。無(wú)論是靈活性還是穩(wěn)定性都得到了極大的提高。

          posted @ 2015-07-20 22:32 wxb1988 閱讀(208) | 評(píng)論 (0)編輯 收藏
          定義:確保一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。

          類型:創(chuàng)建類模式

          類圖:

          類圖知識(shí)點(diǎn):

          1.類圖分為三部分,依次是類名、屬性、方法

          2.以<<開(kāi)頭和以>>結(jié)尾的為注釋信息

          3.修飾符+代表public,-代表private,#代表protected,什么都沒(méi)有代表包可見(jiàn)。

          4.帶下劃線的屬性或方法代表是靜態(tài)的。

          5.對(duì)類圖中對(duì)象的關(guān)系不熟悉的朋友可以參考文章:設(shè)計(jì)模式中類的關(guān)系

          單例模式應(yīng)該是23種設(shè)計(jì)模式中最簡(jiǎn)單的一種模式了。它有以下幾個(gè)要素:

          • 私有的構(gòu)造方法
          • 指向自己實(shí)例的私有靜態(tài)引用
          • 以自己實(shí)例為返回值的靜態(tài)的公有的方法

                  單例模式根據(jù)實(shí)例化對(duì)象時(shí)機(jī)的不同分為兩種:一種是餓漢式單例,一種是懶漢式單例。餓漢式單例在單例類被加載時(shí)候,就實(shí)例化一個(gè)對(duì)象交給自己的引用;而懶漢式在調(diào)用取得實(shí)例方法的時(shí)候才會(huì)實(shí)例化對(duì)象。代碼如下:

          餓漢式單例

          1. public class Singleton {  
          2.     private static Singleton singleton = new Singleton();  
          3.     private Singleton(){}  
          4.     public static Singleton getInstance(){  
          5.         return singleton;  
          6.     }  
          7. }  

          懶漢式單例

          1. public class Singleton {  
          2.     private static Singleton singleton;  
          3.     private Singleton(){}  
          4.       
          5.     public static synchronized Singleton getInstance(){  
          6.         if(singleton==null){  
          7.             singleton = new Singleton();  
          8.         }  
          9.         return singleton;  
          10.     }  
          11. }  

          單例模式的優(yōu)點(diǎn):

          • 在內(nèi)存中只有一個(gè)對(duì)象,節(jié)省內(nèi)存空間。
          • 避免頻繁的創(chuàng)建銷毀對(duì)象,可以提高性能。
          • 避免對(duì)共享資源的多重占用。
          • 可以全局訪問(wèn)。

          適用場(chǎng)景:由于單例模式的以上優(yōu)點(diǎn),所以是編程中用的比較多的一種設(shè)計(jì)模式。我總結(jié)了一下我所知道的適合使用單例模式的場(chǎng)景:

          • 需要頻繁實(shí)例化然后銷毀的對(duì)象。
          • 創(chuàng)建對(duì)象時(shí)耗時(shí)過(guò)多或者耗資源過(guò)多,但又經(jīng)常用到的對(duì)象。
          • 有狀態(tài)的工具類對(duì)象。
          • 頻繁訪問(wèn)數(shù)據(jù)庫(kù)或文件的對(duì)象。
          • 以及其他我沒(méi)用過(guò)的所有要求只有一個(gè)對(duì)象的場(chǎng)景。

          單例模式注意事項(xiàng):

          • 只能使用單例類提供的方法得到單例對(duì)象,不要使用反射,否則將會(huì)實(shí)例化一個(gè)新對(duì)象。
          • 不要做斷開(kāi)單例類對(duì)象與類中靜態(tài)引用的危險(xiǎn)操作。
          • 多線程使用單例使用共享資源時(shí),注意線程安全問(wèn)題。

          關(guān)于java中單例模式的一些爭(zhēng)議:

          單例模式的對(duì)象長(zhǎng)時(shí)間不用會(huì)被jvm垃圾收集器收集嗎

                  看到不少資料中說(shuō):如果一個(gè)單例對(duì)象在內(nèi)存中長(zhǎng)久不用,會(huì)被jvm認(rèn)為是一個(gè)垃圾,在執(zhí)行垃圾收集的時(shí)候會(huì)被清理掉。對(duì)此這個(gè)說(shuō)法,筆者持懷疑態(tài)度,筆者本人的觀點(diǎn)是:在hotspot虛擬機(jī)1.6版本中,除非人為地?cái)嚅_(kāi)單例中靜態(tài)引用到單例對(duì)象的聯(lián)接,否則jvm垃圾收集器是不會(huì)回收單例對(duì)象的。

          對(duì)于這個(gè)爭(zhēng)議,筆者單獨(dú)寫了一篇文章進(jìn)行討論,如果您有不同的觀點(diǎn)或者有過(guò)這方面的經(jīng)歷請(qǐng)進(jìn)入文章單例模式討論篇:?jiǎn)卫J脚c垃圾收集參與討論。

           

          在一個(gè)jvm中會(huì)出現(xiàn)多個(gè)單例嗎

                  在分布式系統(tǒng)、多個(gè)類加載器、以及序列化的的情況下,會(huì)產(chǎn)生多個(gè)單例,這一點(diǎn)是無(wú)庸置疑的。那么在同一個(gè)jvm中,會(huì)不會(huì)產(chǎn)生單例呢?使用單例提供的getInstance()方法只能得到同一個(gè)單例,除非是使用反射方式,將會(huì)得到新的單例。代碼如下

          1. Class c = Class.forName(Singleton.class.getName());  
          2. Constructor ct = c.getDeclaredConstructor();  
          3. ct.setAccessible(true);  
          4. Singleton singleton = (Singleton)ct.newInstance();  

          這樣,每次運(yùn)行都會(huì)產(chǎn)生新的單例對(duì)象。所以運(yùn)用單例模式時(shí),一定注意不要使用反射產(chǎn)生新的單例對(duì)象。

           

          懶漢式單例線程安全嗎

                  主要是網(wǎng)上的一些說(shuō)法,懶漢式的單例模式是線程不安全的,即使是在實(shí)例化對(duì)象的方法上加synchronized關(guān)鍵字,也依然是危險(xiǎn)的,但是筆者經(jīng)過(guò)編碼測(cè)試,發(fā)現(xiàn)加synchronized關(guān)鍵字修飾后,雖然對(duì)性能有部分影響,但是卻是線程安全的,并不會(huì)產(chǎn)生實(shí)例化多個(gè)對(duì)象的情況。

           

          單例模式只有餓漢式和懶漢式兩種嗎

                  餓漢式單例和懶漢式單例只是兩種比較主流和常用的單例模式方法,從理論上講,任何可以實(shí)現(xiàn)一個(gè)類只有一個(gè)實(shí)例的設(shè)計(jì)模式,都可以稱為單例模式。

           

          單例類可以被繼承嗎

                  餓漢式單例和懶漢式單例由于構(gòu)造方法是private的,所以他們都是不可繼承的,但是其他很多單例模式是可以繼承的,例如登記式單例。

           

          餓漢式單例好還是懶漢式單例好

                  在java中,餓漢式單例要優(yōu)于懶漢式單例。C++中則一般使用懶漢式單例。

          單例模式比較簡(jiǎn)單,在此就不舉例代碼演示了。

          單例模式與垃圾回收

                 Jvm的垃圾回收機(jī)制到底會(huì)不會(huì)回收掉長(zhǎng)時(shí)間不用的單例模式對(duì)象,這的確是一個(gè)比較有爭(zhēng)議性的問(wèn)題。將這一部分內(nèi)容單獨(dú)成篇的目的也是為了與廣大博友廣泛的討論一下這個(gè)問(wèn)題。為了能讓更多的人看到這篇文章,請(qǐng)各位博友看完文章之后,點(diǎn)一下“頂”,讓本篇文章排名盡量的靠前。筆者在此謝過(guò)。


          討論命題:當(dāng)一個(gè)單例的對(duì)象長(zhǎng)久不用時(shí),會(huì)不會(huì)被jvm的垃圾收集機(jī)制回收。

                  首先說(shuō)一下為什么會(huì)產(chǎn)生這一疑問(wèn),筆者本人再此之前從來(lái)沒(méi)有考慮過(guò)垃圾回收對(duì)單例模式的影響,直到去年讀了一本書,《設(shè)計(jì)模式之禪》秦小波著。在書中提到在j2ee應(yīng)用中,jvm垃圾回收機(jī)制會(huì)把長(zhǎng)久不用的單例類對(duì)象當(dāng)作垃圾,并在cpu空閑的時(shí)候?qū)ζ溥M(jìn)行回收。之前讀過(guò)的幾本設(shè)計(jì)模式的書,包括《java與模式》,書中都沒(méi)有提到j(luò)vm垃圾回收機(jī)制對(duì)單例的影響。并且在工作過(guò)程中,也沒(méi)有過(guò)單例對(duì)象被回收的經(jīng)歷,加上工作中很多前輩曾經(jīng)告誡過(guò)筆者:盡量不要聲明太多的靜態(tài)屬性,因?yàn)檫@些靜態(tài)屬性被加載后不會(huì)被釋放。因此對(duì)jvm垃圾收集會(huì)回收單例對(duì)象這一說(shuō)法持懷疑態(tài)度。漸漸地,發(fā)現(xiàn)在同事中和網(wǎng)上的技術(shù)人員中,對(duì)這一問(wèn)題也基本上是鮮明的對(duì)立兩派。那么到底jvm會(huì)不會(huì)回收長(zhǎng)久不用的單例對(duì)象呢。

                  對(duì)這一問(wèn)題,筆者本人的觀點(diǎn)是:不會(huì)回收。

          下面給出本人的測(cè)試代碼

          1. class Singleton {  
          2.     private byte[] a = new byte[6*1024*1024];  
          3.     private static Singleton singleton = new Singleton();  
          4.     private Singleton(){}  
          5.       
          6.     public static Singleton getInstance(){  
          7.         return singleton;  
          8.     }  
          9. }  
          10.   
          11. class Obj {  
          12.     private byte[] a = new byte[3*1024*1024];  
          13. }  
          14.   
          15. public class Client{  
          16.     public static void main(String[] args) throws Exception{  
          17.         Singleton.getInstance();  
          18.         while(true){  
          19.             new Obj();  
          20.         }  
          21.     }  
          22. }  

                  本段程序的目的是模擬j2ee容器,首先實(shí)例化單例類,這個(gè)單例類占6M內(nèi)存,然后程序進(jìn)入死循環(huán),不斷的創(chuàng)建對(duì)象,逼迫jvm進(jìn)行垃圾回收,然后觀察垃圾收集信息,如果進(jìn)行垃圾收集后,內(nèi)存仍然大于6M,則說(shuō)明垃圾回收不會(huì)回收單例對(duì)象。

                  運(yùn)行本程序使用的虛擬機(jī)是hotspot虛擬機(jī),也就是我們使用的最多的java官方提供的虛擬機(jī),俗稱jdk,版本是jdk1.6.0_12

                  運(yùn)行時(shí)vm arguments參數(shù)為:-verbose:gc -Xms20M -Xmx20M,意思是每次jvm進(jìn)行垃圾回收時(shí)顯示內(nèi)存信息,jvm的內(nèi)存設(shè)為固定20M。

          運(yùn)行結(jié)果:

          ……

          [Full GC 18566K->6278K(20352K), 0.0101066 secs]

          [GC 18567K->18566K(20352K), 0.0001978 secs]

          [Full GC 18566K->6278K(20352K), 0.0088229 secs]

          ……

                  從運(yùn)行結(jié)果中可以看到總有6M空間沒(méi)有被收集。因此,筆者認(rèn)為,至少在hotspot虛擬機(jī)中,垃圾回收是不會(huì)回收單例對(duì)象的。

                  后來(lái)查閱了一些相關(guān)的資料,hotspot虛擬機(jī)的垃圾收集算法使用根搜索算法。這個(gè)算法的基本思路是:對(duì)任何“活”的對(duì)象,一定能最終追溯到其存活在堆棧或靜態(tài)存儲(chǔ)區(qū)之中的引用。通過(guò)一系列名為根(GC Roots)的引用作為起點(diǎn),從這些根開(kāi)始搜索,經(jīng)過(guò)一系列的路徑,如果可以到達(dá)java堆中的對(duì)象,那么這個(gè)對(duì)象就是“活”的,是不可回收的。可以作為根的對(duì)象有:

          • 虛擬機(jī)棧(棧楨中的本地變量表)中的引用的對(duì)象。
          • 方法區(qū)中的類靜態(tài)屬性引用的對(duì)象。
          • 方法區(qū)中的常量引用的對(duì)象。
          • 本地方法棧中JNI的引用的對(duì)象。

                  方法區(qū)是jvm的一塊內(nèi)存區(qū)域,用來(lái)存放類相關(guān)的信息。很明顯,java中單例模式創(chuàng)建的對(duì)象被自己類中的靜態(tài)屬性所引用,符合第二條,因此,單例對(duì)象不會(huì)被jvm垃圾收集。

                  雖然jvm堆中的單例對(duì)象不會(huì)被垃圾收集,但是單例類本身如果長(zhǎng)時(shí)間不用會(huì)不會(huì)被收集呢?因?yàn)閖vm對(duì)方法區(qū)也是有垃圾收集機(jī)制的。如果單例類被收集,那么堆中的對(duì)象就會(huì)失去到根的路徑,必然會(huì)被垃圾收集掉。對(duì)此,筆者查閱了hotspot虛擬機(jī)對(duì)方法區(qū)的垃圾收集方法,jvm卸載類的判定條件如下:

          • 該類所有的實(shí)例都已經(jīng)被回收,也就是java堆中不存在該類的任何實(shí)例。
          • 加載該類的ClassLoader已經(jīng)被回收。
          • 該類對(duì)應(yīng)的java.lang.Class對(duì)象沒(méi)有任何地方被引用,無(wú)法在任何地方通過(guò)反射訪問(wèn)該類的方法。

                  只有三個(gè)條件都滿足,jvm才會(huì)在垃圾收集的時(shí)候卸載類。顯然,單例的類不滿足條件一,因此單例類也不會(huì)被卸載。也就是說(shuō),只要單例類中的靜態(tài)引用指向jvm堆中的單例對(duì)象,那么單例類和單例對(duì)象都不會(huì)被垃圾收集,依據(jù)根搜索算法,對(duì)象是否會(huì)被垃圾收集與未被使用時(shí)間長(zhǎng)短無(wú)關(guān),僅僅在于這個(gè)對(duì)象是不是“活”的。假如一個(gè)對(duì)象長(zhǎng)久未使用而被回收,那么收集算法應(yīng)該是最近最長(zhǎng)未使用算法,最近最長(zhǎng)未使用算法一般用在操作系統(tǒng)的內(nèi)外存交換中,如果用在虛擬機(jī)垃圾回收中,豈不是太不安全了?以上是筆者的觀點(diǎn)。

                  因此筆者的觀點(diǎn)是:在hotspot虛擬機(jī)1.6版本中,除非人為地?cái)嚅_(kāi)單例中靜態(tài)引用到單例對(duì)象的聯(lián)接,否則jvm垃圾收集器是不會(huì)回收單例對(duì)象的。

          posted @ 2015-07-20 22:30 wxb1988 閱讀(218) | 評(píng)論 (0)編輯 收藏
               摘要: 單例對(duì)象(Singleton)是一種常用的設(shè)計(jì)模式。在Java應(yīng)用中,單例對(duì)象能保證在一個(gè)JVM中,該對(duì)象只有一個(gè)實(shí)例存在。這樣的模式有幾個(gè)好處:1、某些類創(chuàng)建比較頻繁,對(duì)于一些大型的對(duì)象,這是一筆很大的系統(tǒng)開(kāi)銷。2、省去了new操作符,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC壓力。3、有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以創(chuàng)建多個(gè)的話,系統(tǒng)完全亂了。(比如一個(gè)軍隊(duì)出現(xiàn)了多個(gè)司令員同...  閱讀全文
          posted @ 2015-07-20 22:28 wxb1988 閱讀(177) | 評(píng)論 (0)編輯 收藏
               摘要: 8.1 女媧造人的故事      東漢《風(fēng)俗通》記錄了一則神話故事:“開(kāi)天辟辟,未有人民,女媧搏,黃土作人……”,講述的內(nèi)容就是大家非常熟悉的女媧造人的故事。開(kāi)天辟地之初,大地上并沒(méi)有生物,只有蒼茫大地,純粹而潔凈的自然環(huán)境,寂靜而又寂寞,于是女媧決定創(chuàng)造一個(gè)新物種(即人類)來(lái)增加世界的繁榮,怎么制造...  閱讀全文
          posted @ 2015-07-20 22:20 wxb1988 閱讀(175) | 評(píng)論 (0)編輯 收藏

          工廠方法模式(Factory Method)

          簡(jiǎn)單工廠模式有一個(gè)問(wèn)題就是,類的創(chuàng)建依賴工廠類,也就是說(shuō),如果想要拓展程序,必須對(duì)工廠類進(jìn)行修改,這違背了閉包原則,所以,從設(shè)計(jì)角度考慮,有一定的問(wèn)題,如何解決?就用到工廠方法模式,創(chuàng)建一個(gè)工廠接口和創(chuàng)建多個(gè)工廠實(shí)現(xiàn)類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。

          請(qǐng)看例子:

          1. public interface Sender {  
          2.     public void Send();  
          3. }  

          兩個(gè)實(shí)現(xiàn)類:

          1. public class MailSender implements Sender {  
          2.     @Override  
          3.     public void Send() {  
          4.         System.out.println("this is mailsender!");  
          5.     }  
          6. }  
          1. public class SmsSender implements Sender {  
          2.   
          3.     @Override  
          4.     public void Send() {  
          5.         System.out.println("this is sms sender!");  
          6.     }  
          7. }  

          兩個(gè)工廠類:

          1. public class SendMailFactory implements Provider {  
          2.       
          3.     @Override  
          4.     public Sender produce(){  
          5.         return new MailSender();  
          6.     }  
          7. }  
          1. public class SendSmsFactory implements Provider{  
          2.   
          3.     @Override  
          4.     public Sender produce() {  
          5.         return new SmsSender();  
          6.     }  
          7. }  

          在提供一個(gè)接口:

          1. public interface Provider {  
          2.     public Sender produce();  
          3. }  

          測(cè)試類:

          1. public class Test {  
          2.   
          3.     public static void main(String[] args) {  
          4.         Provider provider = new SendMailFactory();  
          5.         Sender sender = provider.produce();  
          6.         sender.Send();  
          7.     }  
          8. }  

          其實(shí)這個(gè)模式的好處就是,如果你現(xiàn)在想增加一個(gè)功能:發(fā)及時(shí)信息,則只需做一個(gè)實(shí)現(xiàn)類,實(shí)現(xiàn)Sender接口,同時(shí)做一個(gè)工廠類,實(shí)現(xiàn)Provider接口,就OK了,無(wú)需去改動(dòng)現(xiàn)成的代碼。這樣做,拓展性較好!



          2、抽象工廠模式

          工廠方法模式和抽象工廠模式不好分清楚,他們的區(qū)別如下:

          工廠方法模式: 一個(gè)抽象產(chǎn)品類,可以派生出多個(gè)具體產(chǎn)品類。    一個(gè)抽象工廠類,可以派生出多個(gè)具體工廠類。    每個(gè)具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例。  抽象工廠模式: 多個(gè)抽象產(chǎn)品類,每個(gè)抽象產(chǎn)品類可以派生出多個(gè)具體產(chǎn)品類。    一個(gè)抽象工廠類,可以派生出多個(gè)具體工廠類。    每個(gè)具體工廠類可以創(chuàng)建多個(gè)具體產(chǎn)品類的實(shí)例,也就是創(chuàng)建的是一個(gè)產(chǎn)品線下的多個(gè)產(chǎn)品。         區(qū)別: 工廠方法模式只有一個(gè)抽象產(chǎn)品類,而抽象工廠模式有多個(gè)。    工廠方法模式的具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例,而抽象工廠模式可以創(chuàng)建多個(gè)。
          工廠方法創(chuàng)建 "一種" 產(chǎn)品,他的著重點(diǎn)在于"怎么創(chuàng)建",也就是說(shuō)如果你開(kāi)發(fā),你的大量代碼很可能圍繞著這種產(chǎn)品的構(gòu)造,初始化這些細(xì)節(jié)上面。也因?yàn)槿绱耍愃频漠a(chǎn)品之間有很多可以復(fù)用的特征,所以會(huì)和模版方法相隨。 

          抽象工廠需要?jiǎng)?chuàng)建一些列產(chǎn)品,著重點(diǎn)在于"創(chuàng)建哪些"產(chǎn)品上,也就是說(shuō),如果你開(kāi)發(fā),你的主要任務(wù)是劃分不同差異的產(chǎn)品線,并且盡量保持每條產(chǎn)品線接口一致,從而可以從同一個(gè)抽象工廠繼承。

          對(duì)于java來(lái)說(shuō),你能見(jiàn)到的大部分抽象工廠模式都是這樣的: ---它的里面是一堆工廠方法,每個(gè)工廠方法返回某種類型的對(duì)象。  比如說(shuō)工廠可以生產(chǎn)鼠標(biāo)和鍵盤。那么抽象工廠的實(shí)現(xiàn)類(它的某個(gè)具體子類)的對(duì)象都可以生產(chǎn)鼠標(biāo)和鍵盤,但可能工廠A生產(chǎn)的是羅技的鍵盤和鼠標(biāo),工廠B是微軟的。  這樣A和B就是工廠,對(duì)應(yīng)于抽象工廠; 每個(gè)工廠生產(chǎn)的鼠標(biāo)和鍵盤就是產(chǎn)品,對(duì)應(yīng)于工廠方法;  用了工廠方法模式,你替換生成鍵盤的工廠方法,就可以把鍵盤從羅技換到微軟。但是用了抽象工廠模式,你只要換家工廠,就可以同時(shí)替換鼠標(biāo)和鍵盤一套。如果你要的產(chǎn)品有幾十個(gè),當(dāng)然用抽象工廠模式一次替換全部最方便(這個(gè)工廠會(huì)替你用相應(yīng)的工廠方法)  所以說(shuō)抽象工廠就像工廠,而工廠方法則像是工廠的一種產(chǎn)品生產(chǎn)線
          posted @ 2015-07-20 22:20 wxb1988 閱讀(165) | 評(píng)論 (0)編輯 收藏

          簡(jiǎn)單工廠模式

          簡(jiǎn)單工廠模式模式分為三種:

          01、普通

          就是建立一個(gè)工廠類,對(duì)實(shí)現(xiàn)了同一接口的一些類進(jìn)行實(shí)例的創(chuàng)建。首先看下關(guān)系圖:

          舉例如下:(我們舉一個(gè)發(fā)送郵件和短信的例子)

          首先,創(chuàng)建二者的共同接口:

          1. public interface Sender {  
          2.     public void Send();  
          3. }  

          其次,創(chuàng)建實(shí)現(xiàn)類:

          1. public class MailSender implements Sender {  
          2.     @Override  
          3.     public void Send() {  
          4.         System.out.println("this is mailsender!");  
          5.     }  
          6. }  
          1. public class SmsSender implements Sender {  
          2.   
          3.     @Override  
          4.     public void Send() {  
          5.         System.out.println("this is sms sender!");  
          6.     }  
          7. }  

          最后,建工廠類:

          1. public class SendFactory {  
          2.   
          3.     public Sender produce(String type) {  
          4.         if ("mail".equals(type)) {  
          5.             return new MailSender();  
          6.         } else if ("sms".equals(type)) {  
          7.             return new SmsSender();  
          8.         } else {  
          9.             System.out.println("請(qǐng)輸入正確的類型!");  
          10.             return null;  
          11.         }  
          12.     }  
          13. }  

          我們來(lái)測(cè)試下:

          1. public class FactoryTest {  
          2.   
          3.     public static void main(String[] args) {  
          4.         SendFactory factory = new SendFactory();  
          5.         Sender sender = factory.produce("sms");  
          6.         sender.Send();  
          7.     }  
          8. }  

          輸出:this is sms sender!

          02、多個(gè)方法

          是對(duì)普通工廠方法模式的改進(jìn),在普通工廠方法模式中,如果傳遞的字符串出錯(cuò),則不能正確創(chuàng)建對(duì)象,而多個(gè)工廠方法模式是提供多個(gè)工廠方法,分別創(chuàng)建對(duì)象。關(guān)系圖:

          將上面的代碼做下修改,改動(dòng)下SendFactory類就行,如下:

          [java] view plaincopypublic class SendFactory {  
             public Sender produceMail(){  
          1.         return new MailSender();  
          2.     }  
          3.       
          4.     public Sender produceSms(){  
          5.         return new SmsSender();  
          6.     }  
          7. }  

          測(cè)試類如下:

          1. public class FactoryTest {  
          2.   
          3.     public static void main(String[] args) {  
          4.         SendFactory factory = new SendFactory();  
          5.         Sender sender = factory.produceMail();  
          6.         sender.Send();  
          7.     }  
          8. }  

          輸出:this is mailsender!

          03、多個(gè)靜態(tài)方法

          將上面的多個(gè)工廠方法模式里的方法置為靜態(tài)的,不需要?jiǎng)?chuàng)建實(shí)例,直接調(diào)用即可。

          1. public class SendFactory {  
          2.       
          3.     public static Sender produceMail(){  
          4.         return new MailSender();  
          5.     }  
          6.       
          7.     public static Sender produceSms(){  
          8.         return new SmsSender();  
          9.     }  
          10. }  
          1. public class FactoryTest {  
          2.   
          3.     public static void main(String[] args) {      
          4.         Sender sender = SendFactory.produceMail();  
          5.         sender.Send();  
          6.     }  
          7. }  

          輸出:this is mailsender!

          總體來(lái)說(shuō),工廠模式適合:凡是出現(xiàn)了大量的產(chǎn)品需要?jiǎng)?chuàng)建,并且具有共同的接口時(shí),可以通過(guò)工廠方法模式進(jìn)行創(chuàng)建。在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創(chuàng)建對(duì)象,第三種相對(duì)于第二種,不需要實(shí)例化工廠類,所以,大多數(shù)情況下,我們會(huì)選用第三種——靜態(tài)工廠方法模式。

          posted @ 2015-07-20 22:05 wxb1988 閱讀(174) | 評(píng)論 (0)編輯 收藏

          簡(jiǎn)單工廠模式解釋: 

                 簡(jiǎn)單工廠模式(Simple Factory Pattern)屬于類的創(chuàng)新型模式,又叫靜態(tài)工廠方法模式(Static FactoryMethod Pattern),是通過(guò)專門定義一個(gè)類來(lái)負(fù)責(zé)創(chuàng)建其他類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類。

          簡(jiǎn)單工廠模式的UML圖: 

                 簡(jiǎn)單工廠模式中包含的角色及其相應(yīng)的職責(zé)如下:

                 工廠角色(Creator):這是簡(jiǎn)單工廠模式的核心,由它負(fù)責(zé)創(chuàng)建所有的類的內(nèi)部邏輯。當(dāng)然工廠類必須能夠被外界調(diào)用,創(chuàng)建所需要的產(chǎn)品對(duì)象。

                 抽象(Product)產(chǎn)品角色:簡(jiǎn)單工廠模式所創(chuàng)建的所有對(duì)象的父類,注意,這里的父類可以是接口也可以是抽象類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。

                 具體產(chǎn)品(Concrete Product)角色:簡(jiǎn)單工廠所創(chuàng)建的具體實(shí)例對(duì)象,這些具體的產(chǎn)品往往都擁有共同的父類。

          簡(jiǎn)單工廠模式深入分析

                 簡(jiǎn)單工廠模式解決的問(wèn)題是如何去實(shí)例化一個(gè)合適的對(duì)象。

                 簡(jiǎn)單工廠模式的核心思想就是:有一個(gè)專門的類來(lái)負(fù)責(zé)創(chuàng)建實(shí)例的過(guò)程。

                 具體來(lái)說(shuō),把產(chǎn)品看著是一系列的類的集合,這些類是由某個(gè)抽象類或者接口派生出來(lái)的一個(gè)對(duì)象樹(shù)。而工廠類用來(lái)產(chǎn)生一個(gè)合適的對(duì)象來(lái)滿足客戶的要求。

                 如果簡(jiǎn)單工廠模式所涉及到的具體產(chǎn)品之間沒(méi)有共同的邏輯,那么我們就可以使用接口來(lái)扮演抽象產(chǎn)品的角色;如果具體產(chǎn)品之間有功能的邏輯或,我們就必須把這些共同的東西提取出來(lái),放在一個(gè)抽象類中,然后讓具體產(chǎn)品繼承抽象類。為實(shí)現(xiàn)更好復(fù)用的目的,共同的東西總是應(yīng)該抽象出來(lái)的。

                 在實(shí)際的的使用中,抽閑產(chǎn)品和具體產(chǎn)品之間往往是多層次的產(chǎn)品結(jié)構(gòu),如下圖所示:

          簡(jiǎn)單工廠模式使用場(chǎng)景分析及代碼實(shí)現(xiàn): 

                 GG請(qǐng)自己的女朋友和眾多美女吃飯,但是GG自己是不會(huì)做飯的或者做的飯很不好,這說(shuō)明GG不用自己去創(chuàng)建各種食物的對(duì)象;各個(gè)美女都有各自的愛(ài)好,到麥當(dāng)勞后她們喜歡吃什么直接去點(diǎn)就行了,麥當(dāng)勞就是生產(chǎn)各種食物的工廠,這時(shí)候GG不用自己動(dòng)手,也可以請(qǐng)這么多美女吃飯,所要做的就是買單O(∩_∩)O哈哈~,其UML圖如下所示:

                 實(shí)現(xiàn)代碼如下:

                 新建立一個(gè)食物的接口:

          package com.diermeng.designPattern.SimpleFactory;

           

          /*

           * 產(chǎn)品的抽象接口

           */

          public interface Food {

              /*

               * 獲得相應(yīng)的食物

               */

              public void get();

          }

          接下來(lái)建立具體的產(chǎn)品:麥香雞和薯?xiàng)l

          package com.diermeng.designPattern.SimpleFactory.impl;

          import com.diermeng.designPattern.SimpleFactory.Food;

           

          /*

           * 麥香雞對(duì)抽象產(chǎn)品接口的實(shí)現(xiàn)

           */

          public class McChicken implements Food{

              /*

               * 獲取一份麥香雞

               */

              public void get(){

                  System.out.println("我要一份麥香雞");

              }

          }

          package com.diermeng.designPattern.SimpleFactory.impl;

          import com.diermeng.designPattern.SimpleFactory.Food;

           

          /*

           * 薯?xiàng)l對(duì)抽象產(chǎn)品接口的實(shí)現(xiàn)

           */

          public class Chips implements Food{

              /*

               * 獲取一份薯?xiàng)l

               */

              public void get(){

                  System.out.println("我要一份薯?xiàng)l");

              }

          }

          現(xiàn)在建立一個(gè)食物加工工廠:

          package com.diermeng.designPattern.SimpleFactory.impl;

          import com.diermeng.designPattern.SimpleFactory.Food;

           

           

          public class FoodFactory {

           

              public static Food getFood(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

                  if(type.equalsIgnoreCase("mcchicken")) {

                      return McChicken.class.newInstance();

           

                  } else if(type.equalsIgnoreCase("chips")) {

                      return Chips.class.newInstance();

                  } else {

                      System.out.println("哎呀!找不到相應(yīng)的實(shí)例化類啦!");

                      return null;

                  }

           

           

              }

          }

          最后我們建立測(cè)試客戶端:

          package com.diermeng.designPattern.SimpleFactory.client;

          import com.diermeng.designPattern.SimpleFactory.Food;

          import com.diermeng.designPattern.SimpleFactory.impl.FoodFactory;

           

          /*

           * 測(cè)試客戶端

           */

          public class SimpleFactoryTest {

              public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

           

                  //實(shí)例化各種食物

                  Food mcChicken = FoodFactory.getFood("McChicken");

                  Food chips = FoodFactory.getFood("Chips");

                  Food eggs = FoodFactory.getFood("Eggs");

           

                  //獲取食物

                  if(mcChicken!=null){

                      mcChicken.get();

                  }

                  if(chips!=null){

                      chips.get();

                  }

                  if(eggs!=null){

                      eggs.get();

                  }

           

           

              }

          }

          輸出的結(jié)果如下:

          哎呀!找不到相應(yīng)的實(shí)例化類啦!

          我要一份麥香雞

          我要一份薯?xiàng)l

          簡(jiǎn)單工廠模式的優(yōu)缺點(diǎn)分析: 

                 優(yōu)點(diǎn):工廠類是整個(gè)模式的關(guān)鍵所在。它包含必要的判斷邏輯,能夠根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類的對(duì)象。用戶在使用時(shí)可以直接根據(jù)工廠類去創(chuàng)建所需的實(shí)例,而無(wú)需了解這些對(duì)象是如何創(chuàng)建以及如何組織的。有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。

                缺點(diǎn):由于工廠類集中了所有實(shí)例的創(chuàng)建邏輯,這就直接導(dǎo)致一旦這個(gè)工廠出了問(wèn)題,所有的客戶端都會(huì)受到牽連;而且由于簡(jiǎn)單工廠模式的產(chǎn)品室基于一個(gè)共同的抽象類或者接口,這樣一來(lái),但產(chǎn)品的種類增加的時(shí)候,即有不同的產(chǎn)品接口或者抽象類的時(shí)候,工廠類就需要判斷何時(shí)創(chuàng)建何種種類的產(chǎn)品,這就和創(chuàng)建何種種類產(chǎn)品的產(chǎn)品相互混淆在了一起,違背了單一職責(zé),導(dǎo)致系統(tǒng)喪失靈活性和可維護(hù)性。而且更重要的是,簡(jiǎn)單工廠模式違背了“開(kāi)放封閉原則”,就是違背了“系統(tǒng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉”的原則,因?yàn)楫?dāng)我新增加一個(gè)產(chǎn)品的時(shí)候必須修改工廠類,相應(yīng)的工廠類就需要重新編譯一遍。

                總結(jié)一下:簡(jiǎn)單工廠模式分離產(chǎn)品的創(chuàng)建者和消費(fèi)者,有利于軟件系統(tǒng)結(jié)構(gòu)的優(yōu)化;但是由于一切邏輯都集中在一個(gè)工廠類中,導(dǎo)致了沒(méi)有很高的內(nèi)聚性,同時(shí)也違背了“開(kāi)放封閉原則”。另外,簡(jiǎn)單工廠模式的方法一般都是靜態(tài)的,而靜態(tài)工廠方法是無(wú)法讓子類繼承的,因此,簡(jiǎn)單工廠模式無(wú)法形成基于基類的繼承樹(shù)結(jié)構(gòu)。

          簡(jiǎn)單工廠模式的實(shí)際應(yīng)用簡(jiǎn)介: 

                 作為一個(gè)最基本和最簡(jiǎn)單的設(shè)計(jì)模式,簡(jiǎn)單工廠模式卻有很非常廣泛的應(yīng)用,我們這里以Java中的JDBC操作數(shù)據(jù)庫(kù)為例來(lái)說(shuō)明。

                  JDBC是SUN公司提供的一套數(shù)據(jù)庫(kù)編程接口API,它利用Java語(yǔ)言提供簡(jiǎn)單、一致的方式來(lái)訪問(wèn)各種關(guān)系型數(shù)據(jù)庫(kù)。Java程序通過(guò)JDBC可以執(zhí)行SQL語(yǔ)句,對(duì)獲取的數(shù)據(jù)進(jìn)行處理,并將變化了的數(shù)據(jù)存回?cái)?shù)據(jù)庫(kù),因此,JDBC是Java應(yīng)用程序與各種關(guān)系數(shù)據(jù)進(jìn)行對(duì)話的一種機(jī)制。用JDBC進(jìn)行數(shù)據(jù)庫(kù)訪問(wèn)時(shí),要使用數(shù)據(jù)庫(kù)廠商提供的驅(qū)動(dòng)程序接口與數(shù)據(jù)庫(kù)管理系統(tǒng)進(jìn)行數(shù)據(jù)交互。

          客戶端要使用使用數(shù)據(jù)時(shí),只需要和工廠進(jìn)行交互即可,這就導(dǎo)致操作步驟得到極大的簡(jiǎn)化,操作步驟按照順序依次為:注冊(cè)并加載數(shù)據(jù)庫(kù)驅(qū)動(dòng),一般使用Class.forName();創(chuàng)建與數(shù)據(jù)庫(kù)的鏈接Connection對(duì)象;創(chuàng)建SQL語(yǔ)句對(duì)象preparedStatement(sql);提交SQL語(yǔ)句,根據(jù)實(shí)際情況使用executeQuery()或者executeUpdate();顯示相應(yīng)的結(jié)果;關(guān)閉數(shù)據(jù)庫(kù)。

          posted @ 2015-07-20 21:58 wxb1988 閱讀(189) | 評(píng)論 (0)編輯 收藏

           在UML類圖中,常見(jiàn)的有以下幾種關(guān)系: 泛化(Generalization),  實(shí)現(xiàn)(Realization),關(guān)聯(lián)(Association),聚合(Aggregation),組合(Composition),依賴(Dependency)

                   1. 泛化(Generalization

                  【泛化關(guān)系】:是一種繼承關(guān)系,表示一般與特殊的關(guān)系,它指定了子類如何特化父類的所有特征和行為。例如:老虎是動(dòng)物的一種,即有老虎的特性也有動(dòng)物的共性。

                  【箭頭指向】:帶三角箭頭的實(shí)線,箭頭指向父類

          UML類圖幾種關(guān)系的總結(jié) 

                  2. 實(shí)現(xiàn)(Realization

                  【實(shí)現(xiàn)關(guān)系】:是一種類與接口的關(guān)系,表示類是接口所有特征和行為的實(shí)現(xiàn).

                  【箭頭指向】:帶三角箭頭的虛線,箭頭指向接口

          UML類圖幾種關(guān)系的總結(jié) 

                  3. 關(guān)聯(lián)(Association)

                  【關(guān)聯(lián)關(guān)系】:是一種擁有的關(guān)系,它使一個(gè)類知道另一個(gè)類的屬性和方法;如:老師與學(xué)生,丈夫與妻子關(guān)聯(lián)可以是雙向的,也可以是單向的。雙向的關(guān)聯(lián)可以有兩個(gè)箭頭或者沒(méi)有箭頭,單向的關(guān)聯(lián)有一個(gè)箭頭。

                  【代碼體現(xiàn)】:成員變量

                  【箭頭及指向】:帶普通箭頭的實(shí)心線,指向被擁有者

          UML類圖幾種關(guān)系的總結(jié) 

                  上圖中,老師與學(xué)生是雙向關(guān)聯(lián),老師有多名學(xué)生,學(xué)生也可能有多名老師。但學(xué)生與某課程間的關(guān)系為單向關(guān)聯(lián),一名學(xué)生可能要上多門課程,課程是個(gè)抽象的東西他不擁有學(xué)生。 

                  下圖為自身關(guān)聯(lián): 

          UML類圖幾種關(guān)系的總結(jié)

                  4. 聚合(Aggregation

                  【聚合關(guān)系】:是整體與部分的關(guān)系,且部分可以離開(kāi)整體而單獨(dú)存在。如車和輪胎是整體和部分的關(guān)系,輪胎離開(kāi)車仍然可以存在。

                  聚合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是強(qiáng)的關(guān)聯(lián)關(guān)系;關(guān)聯(lián)和聚合在語(yǔ)法上無(wú)法區(qū)分,必須考察具體的邏輯關(guān)系。

                  【代碼體現(xiàn)】:成員變量

                  【箭頭及指向】:帶空心菱形的實(shí)心線,菱形指向整體

          UML類圖幾種關(guān)系的總結(jié) 

                  5. 組合(Composition)

                  【組合關(guān)系】:是整體與部分的關(guān)系,但部分不能離開(kāi)整體而單獨(dú)存在。如公司和部門是整體和部分的關(guān)系,沒(méi)有公司就不存在部門。

                 組合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是比聚合關(guān)系還要強(qiáng)的關(guān)系,它要求普通的聚合關(guān)系中代表整體的對(duì)象負(fù)責(zé)代表部分的對(duì)象的生命周期。

          【代碼體現(xiàn)】:成員變量

          【箭頭及指向】:帶實(shí)心菱形的實(shí)線,菱形指向整體

          UML類圖幾種關(guān)系的總結(jié)

                  6. 依賴(Dependency)

                  【依賴關(guān)系】:是一種使用的關(guān)系,即一個(gè)類的實(shí)現(xiàn)需要另一個(gè)類的協(xié)助,所以要盡量不使用雙向的互相依賴.

                  【代碼表現(xiàn)】:局部變量、方法的參數(shù)或者對(duì)靜態(tài)方法的調(diào)用

                  【箭頭及指向】:帶箭頭的虛線,指向被使用者

          UML類圖幾種關(guān)系的總結(jié) 

                  各種關(guān)系的強(qiáng)弱順序:

                  泛化 = 實(shí)現(xiàn) > 組合 > 聚合 > 關(guān)聯(lián) > 依賴 

                  下面這張UML圖,比較形象地展示了各種類圖關(guān)系:

          UML類圖幾種關(guān)系的總結(jié)

          posted @ 2015-07-19 22:39 wxb1988 閱讀(157) | 評(píng)論 (0)編輯 收藏
               摘要: Longronglin之設(shè)計(jì)模式:Christopher Alexander 說(shuō)過(guò):“每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問(wèn)題,以及該問(wèn)題的解決方案的核心。這樣,你就能一次又一次地使用該方案而不必做重復(fù)勞動(dòng)”。模式描述為:在一定環(huán)境中解決某一問(wèn)題的方案,包括三個(gè)基本元素--問(wèn)題,解決方案和環(huán)境。閱讀類圖和對(duì)象圖請(qǐng)先學(xué)習(xí)UML創(chuàng)建模式 結(jié)構(gòu)模式 行為模式創(chuàng)建...  閱讀全文
          posted @ 2015-07-17 16:40 wxb1988 閱讀(237) | 評(píng)論 (0)編輯 收藏
          主站蜘蛛池模板: 桦甸市| 广灵县| 新乡县| 大同县| 桐庐县| 丰顺县| 泰兴市| 南郑县| 明光市| 修武县| 沐川县| 于田县| 博湖县| 成安县| 敖汉旗| 周口市| 赣州市| 福清市| 开原市| 肃南| 八宿县| 浦县| 罗山县| 荆门市| 古交市| 巴马| 陆河县| 宿州市| 邢台市| 沈丘县| 尚义县| 安乡县| 陵水| 富锦市| 衡阳市| 石屏县| 门头沟区| 遂平县| 衡山县| 丹江口市| 青海省|