設計模式系列-工廠模式

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

     1、案例設想

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

  1. static void Main(string[] args)  
  2. {  
  3.     //是否感應到人 默認是  
  4.     bool isOpen = true;  
  5.  
  6.     //普通燈泡  
  7.     Bulb bulb = new Bulb();  
  8.  
  9.     //感應是否生效  
  10.     if (isOpen)//默認生效  
  11.     {  
  12.         //感應器控制燈泡發光  
  13.         Induction induction = new Induction();  
  14.         induction.Open(bulb);  
  15.     }  
  16. }  
  17.  
  18. /// <summary>  
  19. /// 感應器  
  20. /// </summary>  
  21. public class Induction  
  22. {  
  23.     //打開終端(燈泡)  
  24.     public void Open(Bulb bulb)  
  25.     {  
  26.         //發光  
  27.         bulb.Luminescence();  
  28.     }  
  29. }  
  30. //燈泡  
  31. public class Bulb  
  32. {  
  33.     //發光  
  34.     public void Luminescence()  
  35.     {  
  36.         //燈泡發光的實現  
  37.     }  

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

  1. //節能燈泡  
  2.   public class FrugalBulb  
  3.  {  
  4.      //節能發光  
  5.      public void FrugalLuminescence()  
  6.      {  
  7.          //節能燈泡發光的實現  
  8.      }  
  9.  } 

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

  1. static void Main(string[] args)  
  2. {  
  3.     //是否感應到人 默認是  
  4.     bool isOpen = true;  
  5.  
  6.     //普通燈泡  
  7.     Bulb bulb = new Bulb();  
  8.     //節能燈泡  
  9.     FrugalBulb fBulb = new FrugalBulb();  
  10.  
  11.     //感應是否生效  
  12.     if (isOpen)//默認生效  
  13.     {  
  14.         //感應器控制燈泡發光  
  15.         Induction induction = new Induction();  
  16.         //拆除原先普通燈泡的接口  
  17.         //induction.Open(bulb);  
  18.  
  19.         //增加節能燈泡的接口  
  20.         induction.OpenFrugal(fBulb);  
  21.     }  
  22. }  
  23.  
  24. /// <summary>  
  25. /// 感應器  
  26. /// </summary>  
  27. public class Induction  
  28. {  
  29.     //打開終端(燈泡)  
  30.     public void Open(Bulb bulb)  
  31.     {  
  32.         //發光  
  33.         bulb.Luminescence();  
  34.     }  
  35.  
  36.     //打開節能終端(燈泡)  
  37.     public void OpenFrugal(FrugalBulb fBulb)  
  38.     {  
  39.         //加入節能發光的調用  
  40.         fBulb.FrugalLuminescence();  
  41.     }  

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

    2、引入工廠

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

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

  1. //燈泡的約定  
  2.   public interface IBulb  
  3. {  
  4.     //統一的發光接口  
  5.     public void Luminescence();  
    

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

  1. //燈泡  
  2.  public class Bulb : IBulb//實現了燈泡的約定、標準  
  3.  {  
  4.      //發光  
  5.      public void Luminescence()  
  6.      {  
  7.          //燈泡發光的實現  
  8.      }  
  9.  }  
  10.  
  11.  //節能燈泡  
  12.  public class FrugalBulb : IBulb //實現了燈泡的約定、標準  
  13.  {  
  14.      //節能發光  
  15.      public void Luminescence()  
  16.      {  
  17.          //節能燈泡發光的實現  
  18.      }  
  19.  } 

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

  1. static void Main(string[] args)  
  2. {  
  3.     //是否感應到人 默認是  
  4.     bool isOpen = true;  
  5.  
  6.     //普通燈泡  
  7.     Bulb bulb = new Bulb();  
  8.     //節能燈泡  
  9.     FrugalBulb fBulb = new FrugalBulb();  
  10.  
  11.     //感應是否生效  
  12.     if (isOpen)//默認生效  
  13.     {  
  14.         //感應器控制燈泡發光  
  15.         Induction induction = new Induction();  
  16.  
  17.         //普通燈泡發光  
  18.         induction.Open(bulb);  
  19.  
  20.         //節能燈泡發光  
  21.         induction.Open(fBulb);  
  22.     }  
  23. }  
  24.  
  25. /// <summary>  
  26. /// 感應器  
  27. /// </summary>  
  28. public class Induction  
  29. {  
  30.     //打開終端(燈泡)  
  31.     public void Open(IBulb bulb)  
  32.     {  
  33.         //發光  
  34.         bulb.Luminescence();  
  35.     }  
  36. }  
  37.  
  38. //燈泡的約定  
  39. public interface IBulb  
  40. {  
  41.     //統一的發光接口  
  42.     public void Luminescence();  
  43. }  
  44.  
  45. //燈泡  
  46. public class Bulb : IBulb//實現了燈泡的約定、標準  
  47. {  
  48.     //發光  
  49.     public void Luminescence()  
  50.     {  
  51.         //燈泡發光的實現  
  52.     }  
  53. }  
  54.  
  55. //節能燈泡  
  56. public class FrugalBulb : IBulb //實現了燈泡的約定、標準  
  57. {  
  58.     //節能發光  
  59.     public void Luminescence()  
  60.     {  
  61.         //節能燈泡發光的實現  
  62.     }  

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

  1. public class MyBulbFactory  
  2. {              
  3.     public static IBulb GetBulb(string bulbName)  
  4.     {  
  5.         IBulb bulb = null;  
  6.         //告訴我你要什麼燈泡,我製造相應的燈泡給你  
  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.                 bulb = new ColorBulb();  
  17.                 break;  
  18.         }  
  19.         return bulb;  
  20.     }  
  21. }  
  22.  
  23. /// <summary>  
  24. /// 感應器  
  25. /// </summary>  
  26. public class Induction  
  27. {  
  28.     //打開終端(燈泡)  
  29.     public void Open(IBulb bulb)  
  30.     {  
  31.         //發光  
  32.         bulb.Luminescence();  
  33.     }  
  34. }  
  35.  
  36. //燈泡的約定  
  37. public interface IBulb  
  38. {  
  39.     //統一的發光接口  
  40.     public void Luminescence();  
  41. }  
  42.  
  43. //燈泡  
  44. public class Bulb : IBulb//實現了燈泡的約定、標準  
  45. {  
  46.     //發光  
  47.     public void Luminescence()  
  48.     {  
  49.         //燈泡發光的實現  
  50.     }  
  51. }  
  52.  
  53. //節能燈泡  
  54. public class FrugalBulb : IBulb //實現了燈泡的約定、標準  
  55. {  
  56.     //節能發光  
  57.     public void Luminescence()  
  58.     {  
  59.         //節能燈泡發光的實現  
  60.     }  
  61. }  
  62.  
  63. //彩色燈泡  
  64. public class ColorBulb : IBulb  
  65. {  
  66.     //彩色發光  
  67.     public void Luminescence()  
  68.     {  
  69.         //彩色燈泡發光的實現  
  70.     }  

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

  1. static void Main(string[] args)  
  2.        {  
  3.            //是否感應到人 默認是  
  4.            bool isOpen = true;  
  5.  
  6.            //感應是否生效  
  7.            if (isOpen)//默認生效  
  8.            {  
  9.                //感應器控制燈泡發光  
  10.                Induction induction = new Induction();  
  11.  
  12.                //我需要普通燈泡  
  13.                IBulb bulb = MyBulbFactory.GetBulb("bulb");  
  14.                //普通燈泡發光  
  15.                induction.Open(bulb);  
  16.  
  17.                //我需要節能燈泡  
  18.                IBulb fBulb = MyBulbFactory.GetBulb("frugalbulb");  
  19.                //節能燈泡發光  
  20.                induction.Open(fBulb);  
  21.  
  22.                //我需要彩色燈泡  
  23.                IBulb cBulb = MyBulbFactory.GetBulb("colorbulb");  
  24.                induction.Open(cBulb);  
  25.            }  
  26.        } 

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

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

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

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

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

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

  1. //學習的約定 規則 行爲  
  2.  public interface ILearn  
  3.  {  
  4.      public void Learn();  
  5.  }  
  6.  
  7.  //人類是個抽象的類型  
  8.  public abstract class Person  
  9.  {  
  10.      //活動  
  11.      public virtual void Activity();  
  12.  }  
  13.  
  14.  //男人類  
  15.  public class Man : Person,ILearn  
  16.  {  
  17.      //人類天生的行爲  
  18.      public override void  Activity()  
  19.      {  
  20.            
  21.      }  
  22.  
  23.      //後天的行爲  
  24.      public void Learn()  
  25.      {  
  26.          //學習追女人  
  27.      }  
  28.  }  
  29.  
  30.  //女人類  
  31.  public class Woman : Person,ILearn  
  32.  {  
  33.      //人類天生的行爲  
  34.      public override void Activity()  
  35.      {  
  36.  
  37.      }  
  38.  
  39.      //後天的行爲  
  40.      public void Learn()  
  41.      {  
  42.          //學習被男人追  
  43.      }  
  44.  } 

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章