設計模式系列-工廠模式


      今天回家一開燈感覺客廳的燈暗了許多,抬頭一看原來是燈泡快壞了,想想這個燈泡也是老式的不如換個新的節能燈泡算了。於是跑到小區對面的德爾泰市場買了同樣接口的節能燈泡,這樣光線又好又可以為自己節約電費,回來后迅速拿起凳子,換了新燈泡感覺亮堂了許多。高興之余就想用代碼去模擬一下這個場景。

     1、案例設想

        設想如果我們編寫一個程序通過聲控感應設備去控制燈光的顯示,那么如何實現呢?我想首先第一步就是需要設計當感應設備捕獲到人的時候如何處理,第二部就是在處理內部控制燈泡發光,例如聲控設備感應到人的時候,控制我們平時的普通燈泡去發光。通過面向對象封裝模擬的代碼如下:

static  void Main( string[] args)  
{  
    // 是否感應到人 默認是  
     bool isOpen =  true;  
     // 普通燈泡  
    Bulb bulb =  new Bulb();  
     // 感應是否生效  
     if (isOpen) // 默認生效  
    {  
         // 感應器控制燈泡發光  
        Induction induction =  new Induction();  
        induction.Open(bulb);  
    }  
}  
///   <summary>   
///  感應器  
///   </summary>   
public  class Induction  
{  

    // 打開終端(燈泡)  
    public  void Open(Bulb bulb)  
   {  
        // 發光  
        bulb.Luminescence();  
    }  
}  
// 燈泡  
public  class Bulb  
{  
    // 發光  
     public  void Luminescence()  
    {  
         // 燈泡發光的實現  
    }  
}

 

那么這個時候,我又想起了開始我燈泡壞了的事情了,我最后換了個節能的燈泡。那么我在用代碼模擬一個節能燈泡的類吧。代碼如下:

  // 節能燈泡   
  public  class FrugalBulb   
 {       
     // 節能發光       
      public  void FrugalLuminescence()       
    {           
        // 節能燈泡發光的實現      
     }  
 } 

 

 那么這個時候我的普通燈泡壞了,為了考慮成本,決定將普通的燈泡替換成節能燈泡,那么就會出現一個問題,當普通燈泡的插孔與節能燈泡的插孔不同時?我們需要將燈泡的插孔也替換掉,並且感應器也要增加對應節能燈泡的調用,這樣就大大的增加了替換的成本,不好的替換方式用代碼模擬實現如下:

static  void Main( string[] args)  
{      
       // 是否感應到人 默認是      
         bool isOpen =  true;      
       // 普通燈泡      
       Bulb bulb =  new Bulb();      
       // 節能燈泡      
       FrugalBulb fBulb =  new FrugalBulb();       
       // 感應是否生效      
        if (isOpen) // 默認生效     
       {          
           // 感應器控制燈泡發光          
           Induction induction =  new Induction();          
           // 拆除原先普通燈泡的接口          
            
// induction.Open(bulb);           
          
// 增加節能燈泡的接口         
            induction.OpenFrugal(fBulb);      
        }  
}   
///   <summary>   
///  感應器  
///   </summary>   
public  class Induction 
 {     
      // 打開終端(燈泡)      
       public  void Open(Bulb bulb)     
     {        
         // 發光        
         bulb.Luminescence();   
     }       
      // 打開節能終端(燈泡)     
       public  void OpenFrugal(FrugalBulb fBulb)          
     {          
          // 加入節能發光的調用        
          fBulb.FrugalLuminescence();     
      }  

 

這樣的話實際生活中我們替換增加了成本,代碼模擬中我們修改了原先的代碼頁增加了成本,那么如何降低這些成本呢?

    2、引入工廠

      分析了上面的內容,我們可以看出的問題有:燈泡實際上都是發光,但是發光的接口不一樣例如:普通燈泡發光調用的是【Luminescence】而節能燈泡發光需要調用【FrugalLuminescence】,如果今后需要替換另一種燈泡則需要進行很大的改動,那么如何解決這個問題呢?就想我們組裝電腦一樣,主板、CPU、硬盤等等,它們之間都互相遵循了同樣的接口。不管是AMD的CPU、還是Inter的CPU,它們之間都用一種同樣的公開接口,將來替換CPU就會很方便,其他硬件同樣。

       那么我們能不能將我們燈泡也想電腦硬件一樣,使用同一的接口進行操作呢?當然沒問題。分析一下既然燈泡都是發光,那么我們就可以將燈泡統一一種協議或者叫約定,即所有燈泡將來都以一種接口呈現。代碼如下:

// 燈泡的約定    
public  interface IBulb  
{      
      // 統一的發光接口      
      void Luminescence();  

 

       有了約定(接口),那么所有的燈泡都遵循這個約定,我們以后如果需要更換燈泡或者引進新品種燈泡,只需要跟替換電腦配件那樣,把舊的拔下來新的插上去,代碼如下:

// 燈泡   
public  class Bulb : IBulb // 實現了燈泡的約定、標准   
{       
      // 發光       
       public  void Luminescence()      
     {           
        // 燈泡發光的實現       
      }   
}    
// 節能燈泡   
public  class FrugalBulb : IBulb  // 實現了燈泡的約定、標准   
{       
     // 節能發光       
      public  void Luminescence()       
    {           
        // 節能燈泡發光的實現       
     }   

 

   這個時候我們在來替換一次燈泡看看,模擬代碼如下:

static  void Main( string[] args)  
{      
        // 是否感應到人 默認是      
         bool isOpen =  true;      
        // 普通燈泡      
        Bulb bulb =  new Bulb();      
       // 節能燈泡      
       FrugalBulb fBulb =  new FrugalBulb(); 
       // 感應是否生效      
       if (isOpen) // 默認生效     
      {          
         // 感應器控制燈泡發光          
         Induction induction =  new Induction();           
         // 普通燈泡發光          
         induction.Open(bulb);           
         // 節能燈泡發光          
         induction.Open(fBulb);      
      }  
}   
///   <summary>   
///  感應器  
///   </summary>   
public  class Induction  
{      
     // 打開終端(燈泡)      
     public  void Open(IBulb bulb)      
    {          
         // 發光          
        bulb.Luminescence();      
    }  
}   
// 燈泡的約定  
public  interface IBulb  
{      
     // 統一的發光接口      
     void Luminescence();  
}   
// 燈泡  
public  class Bulb : IBulb // 實現了燈泡的約定、標准  {      
    
// 發光     
      public  void Luminescence()     
    {         
          // 燈泡發光的實現     
     }  
}   
// 節能燈泡  
public  class FrugalBulb : IBulb  // 實現了燈泡的約定、標准  
{     
      // 節能發光      
      public  void Luminescence()      
    {          
         // 節能燈泡發光的實現      
     }  

 

   這個時候還有個問題,如果我們將來需要支持彩色燈泡怎么辦?我們是不是要增加一個彩色燈泡的類實現燈泡的約定接口,還需要在調用方寫入調用的代碼。這個時候我們就可以使用工廠類維護這些燈泡,例如:我的燈泡工廠,目前可以制造,普通燈泡,節能燈泡,彩色燈泡。以后我們需要其中哪種燈泡,就通知工廠來供貨。代碼如下:

public  class MyBulbFactory  
{                  
      public  static IBulb GetBulb( string bulbName)      
     {          
          IBulb bulb =  null;          
           // 告訴我你要什么燈泡,我制造相應的燈泡給你          
           switch (bulbName)          
          {              
                case  " bulb ":                  
               bulb =  new Bulb();                       
                break;                              
                case  " frugalbulb ":                  
               bulb =  new FrugalBulb();      
                break;                  
                case  " colorbulb ":  
                
                bulb =  new ColorBulb();  
                 break;          
           }          
        return bulb;      
     }  
}   
///   <summary>   
///  感應器  
///   </summary>   
public  class Induction  
{      
       // 打開終端(燈泡)      
       public  void Open(IBulb bulb)      
      {          
             // 發光          
            bulb.Luminescence();      
      }  
}   
  // 燈泡的約定 
  public  interface IBulb  
{      
       // 統一的發光接口      
       void Luminescence();  
}   
// 燈泡  
public  class Bulb : IBulb // 實現了燈泡的約定、標准  {      
      
// 發光     
        public  void Luminescence()      
      {         
              // 燈泡發光的實現      
       }  
}   
// 節能燈泡  
public  class FrugalBulb : IBulb  // 實現了燈泡的約定、標准  
{      
       // 節能發光      
       public  void Luminescence()      
     {          
         // 節能燈泡發光的實現      
      }  
}   
// 彩色燈泡  
public  class ColorBulb : IBulb  
{      
       // 彩色發光      
        public  void Luminescence()      
      {          
             // 彩色燈泡發光的實現      
       }  

 

   這樣將來我們需要什么,只需要告訴工廠我要什么,工廠就會給我們提供了統一接口的燈泡,提供我們使用。 主函數調用代碼如下:

static  void Main( string[] args)         {             
      // 是否感應到人 默認是             
      bool isOpen =  true;              
      // 感應是否生效            
       if (isOpen) // 默認生效             
     {                 
           // 感應器控制燈泡發光                 
          Induction induction =  new Induction();                  
           // 我需要普通燈泡                
           IBulb bulb = MyBulbFactory.GetBulb( " bulb ");                 
           // 普通燈泡發光                
           induction.Open(bulb);                  
           // 我需要節能燈泡                 
          IBulb fBulb = MyBulbFactory.GetBulb     ( " frugalbulb ");                 
           // 節能燈泡發光                 
          induction.Open(fBulb);                  
           // 我需要彩色燈泡                 
          IBulb cBulb = MyBulbFactory.GetBulb( " colorbulb ");                 
          induction.Open(cBulb);             
     }         

 

   使用工廠模式,可以有效的減少更換同類部件的成本。

  3、抽象類與接口的個人理解

    很多人都很迷惑什么時候應該使用接口,什么時候應該使用抽象類呢?

    在.NET企業級架構設計一書中,作者對這方面的解釋為:“在那些不支持多繼承的面向對象語言(例如,java、C#、和 Visual Basic.NET)中,我們一般傾向於使用接口,因為這樣其基類仍有挑選的余地,若支持多繼承,則是使用上的偏好了。”

    融合了上面的概念后,我總結的是,當類型之間存在集成關系時,我們使用抽象類,例如一個抽象類人類,那么男人和女人都是人類,他們之間存在着這種派生關系,當類型之間需要遵循一系列約定或者規則時使用接口,例如男人和女人都要學習,工作等等。

     也就是說,類型天生的部分封裝成抽象類,后天添加的規則方法,使用接口,代碼實現如下【個人理解僅供參考】:

// 學習的約定 規則 行為   
public  interface ILearn   
{       
       void Learn();   
}    
// 人類是個抽象的類型   
public  abstract  class Person   
{       
      // 活動       
      public  abstract  void Activity();   
}    
// 男人類   
public  class Man : Person,ILearn   
{       
      // 人類天生的行為       
      public  override  void  Activity()            
     {                  
     }     
   
      // 后天的行為       
      public  void Learn()       
     {           
      // 學習追女人       
     }   
}    
// 女人類   
public  class Woman : Person,ILearn   
{       
      // 人類天生的行為       
      public  override  void Activity()
     {        
     }        
      // 后天的行為       
      public  void Learn()       
     {           
           // 學習被男人追       
     }   

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM