设计模式系列-工厂模式

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

     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()       
     {           
           // 学习被男人追       
     }   

 

 

   

你可能感兴趣的:(设计模式)