设计模式系列-工厂模式

      今天回家一开灯感觉客厅的灯暗了许多,抬头一看原来是灯泡快坏了,想想这个灯泡也是老式的不如换个新的节能灯泡算了。于是跑到小区对面的德尔泰市场买了同样接口的节能灯泡,这样光线又好又可以为自己节约电费,回来后迅速拿起凳子,换了新灯泡感觉亮堂了许多。高兴之余就想用代码去模拟一下这个场景。

     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.  } 

   

你可能感兴趣的:(设计模式,接口,抽象类,C#,工厂模式)