設(shè)計(jì)模式系列-工廠方法模式

       回顧下設(shè)計(jì)模式系列《工廠模式》那片文章,里面描述了如何利用工廠模式來(lái)模擬一個(gè)換燈泡的場(chǎng)景,該場(chǎng)景中模擬了:普通燈泡、節(jié)能燈泡、彩色燈泡。它們統(tǒng)一由一個(gè)工廠(工廠類)來(lái)創(chuàng)造,我們需要使用哪種燈泡時(shí),只需通知工廠類給我們打造一個(gè)相同的燈泡即可,類圖如下:

創(chuàng)新互聯(lián)自2013年創(chuàng)立以來(lái),是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站建設(shè)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元蘇家屯做網(wǎng)站,已為上家服務(wù),為蘇家屯各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575

       設(shè)計(jì)模式系列-工廠方法模式

      由上面邊的類圖可見(jiàn),所有類型的燈泡都由燈泡工廠來(lái)創(chuàng)建,那這個(gè)時(shí)候,制造燈泡的工廠因?yàn)槠髽I(yè)擴(kuò)大了,需要增加產(chǎn)量,那么此時(shí)一個(gè)工廠肯定是應(yīng)付不過(guò)來(lái)了,而且當(dāng)前一個(gè)工廠所造的燈泡種類也多,更加加大了工廠的制造壓力,此時(shí),企業(yè)擴(kuò)建的最好辦法就是,增加工廠,各自工廠都只專注于一種燈泡的制造。

     1.工廠方法模式

     首先我們來(lái)看看什么是工廠方法模式:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類。工廠方法使一個(gè)類的實(shí)例化延遲到其子類。

     工廠方法模式類圖如下:

      設(shè)計(jì)模式系列-工廠方法模式

      Product:定義工廠方法所創(chuàng)建的對(duì)象的接口。相當(dāng)于上邊場(chǎng)景中的燈泡抽象。

      ConcreteProduct:具體實(shí)現(xiàn)Product抽象的具體產(chǎn)品類。相當(dāng)于上邊場(chǎng)景中的具體燈泡。

      Creator:聲明工廠方法,該方法返回一個(gè)Product類型的對(duì)象。

      ConcreteCreator:重定義工廠方法返回一個(gè)ConcreteProduct實(shí)例。

      可能這會(huì)大家看完這個(gè)類圖會(huì)有點(diǎn)模糊,不過(guò)沒(méi)關(guān)系,接下來(lái)我們利用工廠方法模式來(lái)實(shí)現(xiàn)我們上邊的場(chǎng)景(企業(yè)擴(kuò)大需要建立更多的工廠)。

      首先,企業(yè)擴(kuò)大了,需要增加產(chǎn)量建立更多的工廠來(lái)創(chuàng)建,為了更好的提高生產(chǎn)效率,每個(gè)工廠只專注于生產(chǎn)一種種類的燈泡,利用工廠方法模式設(shè)計(jì)的類圖如下:

      設(shè)計(jì)模式系列-工廠方法模式

      邊分析邊實(shí)現(xiàn)代碼:

      第一步,工廠擴(kuò)大了,所造的產(chǎn)品還是燈泡,所以我們還是要把燈泡先抽象出來(lái),為何要抽象請(qǐng)參考《工廠模式》這篇文章。

  1. //燈泡的約定   
  2. public interface IBulb    
  3. {    
  4.     //統(tǒng)一的發(fā)光接口   
  5.     public void Luminescence();    
  6. }  

      第二步,還是實(shí)現(xiàn)目前所有種類的具體燈泡類型。代碼如下:

  1. //燈泡   
  2. public class Bulb : IBulb//實(shí)現(xiàn)了燈泡的約定、標(biāo)準(zhǔn)  {       
  3.       //發(fā)光      
  4.        public void Luminescence()        
  5.       {           
  6.              //燈泡發(fā)光的實(shí)現(xiàn)       
  7.        }    
  8. }     
  9. //節(jié)能燈泡   
  10. public class FrugalBulb : IBulb //實(shí)現(xiàn)了燈泡的約定、標(biāo)準(zhǔn)   
  11. {        
  12.       //節(jié)能發(fā)光       
  13.       public void Luminescence()        
  14.      {            
  15.         //節(jié)能燈泡發(fā)光的實(shí)現(xiàn)       
  16.       }    
  17. }     
  18. //彩色燈泡   
  19. public class ColorBulb : IBulb    
  20. {        
  21.       //彩色發(fā)光       
  22.        public void Luminescence()        
  23.       {            
  24.             //彩色燈泡發(fā)光的實(shí)現(xiàn)       
  25.        }    
  26. }  
     第三步,因?yàn)樵黾恿斯S,但是每個(gè)工廠都有一個(gè)共同的行為那就是制造燈泡,因此為了將來(lái)更方便的增加工廠,我們把工廠也抽象,代碼如下:
  1. //工廠的抽象 
  2. public interface IMyBulbFactory  
  3. {  
  4.     IBulb GetBulb();//將來(lái)每個(gè)工廠都有制造燈泡的行為 

     第四步,實(shí)現(xiàn)制造每個(gè)種類燈泡的具體工廠,每個(gè)工廠都只制造自己所造種類的燈泡,代碼如下:

  1. //制造普通燈泡的工廠 
  2.    public class BulbFactory : IMyBulbFactory  
  3.    {  
  4.        //該工廠制造燈泡的行為 只能制造普通燈泡 
  5.        public IBulb GetBulb()  
  6.        {  
  7.            return new Bulb();  
  8.        }  
  9.    }  
  10.  
  11.    //制造節(jié)能燈泡的工廠 
  12.    public class FrugalBulbFactroy : IMyBulbFactory  
  13.    {  
  14.        //該工廠制造燈泡的行為 只能制造節(jié)能燈泡 
  15.        public IBulb GetBulb()  
  16.        {  
  17.            return new FrugalBulb();  
  18.        }  
  19.    }  
  20.  
  21.    //制造節(jié)能燈泡的工廠 
  22.    public class ColorBulbFactroy : IMyBulbFactory  
  23.    {  
  24.        //該工廠制造燈泡的行為 只能制造彩色燈泡 
  25.        public IBulb GetBulb()  
  26.        {  
  27.            return new ColorBulb();  
  28.        }  
  29.    }  
     這樣,就滿足了企業(yè)擴(kuò)大了,產(chǎn)量提高的問(wèn)題了,需要什么樣的燈泡我們只需要到具體的工廠去獲取對(duì)應(yīng)的燈泡就可以啦,主函數(shù)調(diào)用如下:
  1.   static void Main(string[] args)  
  2.         {  
  3.             //需要普通燈泡 
  4.             IMyBulbFactory bulbFactory = new BulbFactory();  
  5.             IBulb bulb = bulbFactory.GetBulb();  
  6.             bulb.Luminescence(); //普通燈泡發(fā)光 
  7.  
  8.             //需要節(jié)能燈泡 
  9.             IMyBulbFactory frugalBulbFactroy = new FrugalBulbFactroy();  
  10.             IBulb frugalBulb = frugalBulbFactroy.GetBulb();  
  11.             frugalBulb.Luminescence(); //節(jié)能燈泡發(fā)光 
  12.  
  13.             //需要彩色燈泡 
  14.             IMyBulbFactory colorbulbFacroty = new ColorBulbFactroy();  
  15.             IBulb colorBulb = colorbulbFacroty.GetBulb();  
  16.             colorBulb.Luminescence(); //彩色燈泡發(fā)光 
  17. }  
          那么我們發(fā)現(xiàn),當(dāng)工廠方法把具體產(chǎn)品的實(shí)例化延遲到具體的工廠類時(shí),在客戶端調(diào)用的時(shí)候,我們必須顯示的制定使用哪個(gè)具體工廠類,這樣又加大了耦合度。     

     2.使用反射的工廠方法模式

      那么如何接觸上邊的耦合度呢?可以通過(guò)C#的反射機(jī)制,將當(dāng)前所有工廠都配置到配置文件中,然后在配置一個(gè)當(dāng)前需要使用的工廠節(jié)點(diǎn),配置文件如下:

  1. <?xml version="1.0" encoding="utf-8" ?> 
  2. <configuration> 
  3.     <appSettings> 
  4.         <!--配置所有現(xiàn)有的工廠--> 
  5.         <add key="bulbFactory" value="設(shè)計(jì)模式系列.工廠方法模式.BulbFactory"></add> 
  6.         <add key="frugalBulbFactory" value="設(shè)計(jì)模式系列.工廠方法模式.FrugalBulbFactroy"></add> 
  7.         <add key="ColorBulbFactory" value="設(shè)計(jì)模式系列.工廠方法模式.ColorBulbFactroy"></add> 
  8.  
  9.         <!--配置當(dāng)前使用的工廠 當(dāng)前使用普通燈泡的工廠 value="bulbFactory"--> 
  10.         <add key="NonFactory" value="bulbFactory"></add> 
  11.     </appSettings> 
  12. </configuration> 

     這是我們還需要封裝一個(gè)專門提供具體工廠的類,為了方便這個(gè)類我就不考慮耦合了度。代碼如下:

  1. //用來(lái)提供當(dāng)前需要使用的工廠 當(dāng)前使用的工廠在配置文件中nonfactoty節(jié)點(diǎn)中配置 
  2.     public class FactroyProvider  
  3.     {  
  4.         public static IMyBulbFactory WhereToFactroy()  
  5.         {  
  6.             string fName = string.Empty;  
  7.             string factoryName = string.Empty;  
  8.             IMyBulbFactory factory = null;  
  9.               
  10.             if(!string.IsNullOrEmpty(ConfigurationManager.AppSettings["NonFactory"]))  
  11.             {  
  12.                 factoryName = ConfigurationManager.AppSettings["NonFactory"];  
  13.                 if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[factoryName]))  
  14.                 {  
  15.                     fName = ConfigurationManager.AppSettings[factoryName];  
  16.                     factory = Assembly.Load("設(shè)計(jì)模式系列").CreateInstance(fName) as IMyBulbFactory;  
  17.                 }  
  18.             }  
  19.               
  20.             return factory;  
  21.         }  
  22.     }  
      通過(guò)反射找到工廠,我們將來(lái)如果又要擴(kuò)大公司規(guī)模只需要增加具體的工廠實(shí)例與產(chǎn)品實(shí)例,在配置文件中配置一下即可。

     3.工廠方法模式與工廠模式的區(qū)別

     說(shuō)道這里,不知道大家會(huì)不會(huì)有一個(gè)疑問(wèn),總之剛開(kāi)始我是有這個(gè)疑問(wèn),疑問(wèn)就是它和工廠模式的區(qū)別是什么呢?

     首先我們回顧下《工廠模式》中的工廠類的代碼,代碼如下:

  1. public class MyBulbFactory    
  2. {                    
  3.      public static IBulb GetBulb(string bulbName)        
  4.      {            
  5.           IBulb bulb = null;            
  6.           //告訴我你要什么燈泡,我制造相應(yīng)的燈泡給你           
  7.           switch (bulbName)            
  8.           {                
  9.                case "bulb":                    
  10.                bulb = new Bulb();                         
  11.                break;                                
  12.                case "frugalbulb":                    
  13.                bulb = new FrugalBulb();        
  14.                break;                    
  15.                case "colorbulb":    
  16.                   
  17.                 bulb = new ColorBulb();    
  18.                 break;            
  19.            }            
  20.        return bulb;        
  21.      }    
  22. }   
     可見(jiàn)將來(lái)我們?nèi)绻枰略鲆环N燈泡,需要修改上面的工廠類,在switch中加入一個(gè)對(duì)應(yīng)的case分支,這樣就違背了開(kāi)放封閉原則,而工廠方法就是將這些產(chǎn)品類型的實(shí)例化延遲到具體的工廠類去實(shí)例化,這樣將來(lái)如果有了新產(chǎn)品就只需要去創(chuàng)建一個(gè)新的工廠類和一個(gè)具體的產(chǎn)品就可以了,也就是說(shuō)工廠方法模式完善了簡(jiǎn)單工廠模式,使它滿足了開(kāi)放封閉原則。但是有個(gè)問(wèn)題,就是客戶端每次調(diào)用的時(shí)候都會(huì)需要制定具體實(shí)例化哪個(gè)工廠類,例如:
  1. //需要普通燈泡 
  2.             IMyBulbFactory bulbFactory = new BulbFactory();//這里就制定了具體的工廠類 
  3.             IBulb bulb = bulbFactory.GetBulb();  
  4.             bulb.Luminescence(); //普通燈泡發(fā)光 

 這樣就增加了耦合性。我們?cè)谏厦媸褂昧朔瓷漕惤獬笋詈希怯忠粋€(gè)疑問(wèn)出來(lái)啦,那么簡(jiǎn)單工廠模式在創(chuàng)建產(chǎn)品類的時(shí)候,如果也使用反射的話那么將來(lái)在新增產(chǎn)品的時(shí)候也就不需要修改工廠類的代碼了,也就是說(shuō)簡(jiǎn)單工廠模式使用反射一樣可以完美的解決開(kāi)放封閉原則的問(wèn)題!

      那么新的問(wèn)題又出來(lái)了,那簡(jiǎn)單工廠模式還有什么作用呢?

      我個(gè)人有兩種理解的方式,僅代表個(gè)人觀點(diǎn),也希望大家都詳細(xì)的說(shuō)說(shuō)自己的觀點(diǎn),不要一句話概括噢~!

      第一種、在早期設(shè)計(jì)模式應(yīng)用的時(shí)候,編程語(yǔ)言還沒(méi)有使用反射的機(jī)制時(shí),使用工廠方法模式來(lái)升級(jí)簡(jiǎn)單工廠模式,使能夠支持開(kāi)放封閉原則。

      第二種、在特殊場(chǎng)景中,工廠方法模式能更好的實(shí)現(xiàn)邏輯的組織,例如本篇文章所使用的場(chǎng)景。

本文題目:設(shè)計(jì)模式系列-工廠方法模式
URL鏈接:http://muchs.cn/article36/pdgcsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站移動(dòng)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司、品牌網(wǎng)站建設(shè)微信小程序、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化