老生常谈,设计模式之我见 - 工厂模式篇

(因家里没有装建模工具,而VS2005的类图老是用不惯,需等以后有时间再补上类图)

有这样一个场景,假设我是一家电器生产公司职员,主要工作是从设计部那里拿到设计好的图纸,然后交给生产部门进行生产,再对生产好的产品进行相关的检测.需要做一套系统来显示测试的结果.

刚开始公司只生产一种型号的冰箱,需要检测的是冰箱的冷冻能力.那我们可能会这样实现:
     public   class  IceBox
    {
        
public   double  FreezePower()  // 冷冻能力
        {
        
return   1 ;
        }
    }

    
public   class  Factory
    {
        
public  IceBox CreateIceBox()
        {
        
return   new  IceBox();
        }
    }

    
public   class  My
    {
        
private   void  ShowInfo()
        {
            IceBox icebox 
=   new  Factory().CreateIceBox();
        MessageBox.Show(icebox.FreezePower().ToString()); 
// 显示1
        }        
    }

看起来很不错,也很简单!不过没多久问题就来了,现在公司又生产了另外一种型号的冰箱,要对两种型号的冰箱进行检测,我们应该怎么做,难道是像下面一样:
     public   class  IceBoxA  // A型冰箱
    {
        
public   double  FreezePower()  // 冷冻能力
        {
        
return   1 ;
        }
    }

    
public   class  IceBoxB  // B型冰箱
    {
        
public   double  FreezePower()  // 冷冻能力
        {
        
return   2 ;
        }
    }

    
public   class  Factory
    {
        
public  IceBoxA CreateIceBoxA()
        {
        
return   new  IceBoxA();
        }

        
public  IceBoxB CreateIceBoxB()
        {
        
return   new  IceBoxB();
        }
    }

    
public   class  My
    {
        
private   void  ShowInfo()
        {
        
if  (测试的是A型冰箱)
        {
                IceBoxA iceboxa 
=   new  Factory().CreateIceBoxA();
            MessageBox.Show(iceboxa.FreezePower().ToString()); 
// 显示1
        }
        
else
        {
                IceBoxB iceboxb 
=   new  Factory().CreateIceBoxB();
            MessageBox.Show(iceboxb.FreezePower().ToString()); 
// 显示2
        }
        }        
    }

看到这里,性子急的人可能会骂起来了,这当然不行,如果我们以后又增加了C,D,E,F..型号,那怎么办?
的确,我们可以做得更好!有经验的高手一般就会这样做:
     public   interface  IIceBox    // 增加冰箱的通用接口
    {
        
double  FreezePower();   // 冷冻能力
    }

    
public   class  IceBoxA : IIceBox  // A型冰箱
    {
        
public   double  FreezePower()  // 冷冻能力
        {
        
return   1 ;
        }
    }

    
public   class  IceBoxB : IIceBox  // B型冰箱
    {
        
public   double  FreezePower()  // 冷冻能力
        {
        
return   2 ;
        }
    }

    
public   class  Factory
    {
        
public  IIceBox CreateIceBox( string  Mode)
        {
        
if  (Mode  ==   " A " return   new  IceBoxA();
        
else   return   new  IceBoxB();
        }
    }

    
public   class  My
    {
        
private   void  ShowInfo()
        {
        Factory factory 
=   new  Factory();
        IIceBox icebox 
=  factory.CreateIceBox( " A " );
        
        MessageBox.Show(icebox.FreezePower().ToString()); 
// 显示1,如上一步换为"B",则显示2
        }        
    }
这比刚才的要好多了吧!My不用知道具体冰箱的型号,如果再增加C型冰箱,扩充也更容易!其实这就叫简单工厂模式!

不过随着公司规模的扩大,又新建了一个工厂,A工厂只生产A型冰箱,B工厂只生产B型冰箱,问题又出来了,总不可
能直接增加一个FactoryB吧,那以后又增加几个工厂呢?
与上面的思想类似,其实我们可以这样做:
     public   interface  IFactory    // 增加工厂的通用接口
    {
        IIceBox CreateIceBox();  
// 生产冰箱
    }

    
public   class  FactoryA : IFactory    // A型工厂
    {
        
public  IIceBox CreateIceBox()  // 生产A型冰箱
        {
        
return   new  IceBoxA();
        }
    }

    
public   class  FactoryB : IFactory   // B型工厂
    {
        
public  IIceBox CreateIceBox()  // 生产B型冰箱
        {
        
return   new  IceBoxB();
        }
    }

    
public   class  My
    {
        
private  IFactory GetFactory( string  Mode)
        {
        
if  (Mode  ==   " A " return   new  FactoryA();
        
else   return   new  FactoryB();
        }

        
private   void  ShowInfo()
        {
        IFactory factory 
=  GetFactory( " A " );
        IIceBox icebox 
=  factory.CreateIceBox();
        MessageBox.Show(icebox.FreezePower().ToString()); 
// 显示1,如上上一步换为"B",则显 示2
        }        
    }
这比直接增加FactoryB要好多了,具体的调用方法不用改变,也不需要知道冰箱的类型!即使再增加工厂C,改动也不大!这就是工厂模式!

不过随着公司规模进一步扩大,出现了这样的需求:
1. 公司不仅要生产冰箱,还要生产冼衣机.
2. 冰箱和洗衣机都分A型和B型.
3. A型工厂生产A型冰箱和洗衣机(投放国内市场),B型工厂生产B型冰箱和洗衣机(出口)

当然我们可以继续在上面的方案上进行扩充:
     public   interface  IWasher    // 增加洗衣机通用接口
    {
        
double  WashPower;   // 洗涤效果
    }

    
public   class  WasherA : IWasher  // 实现A型冰箱
    {
        
public   double  WashPower()  // 洗涤效果
        {
        
return   1 ;
        }
    }

    
public   class  WasherB : IWasher  // 实现B型冰箱
    {
        
public   double  WashPower()  // 洗涤效果
        {
        
return   2 ;
        }
    }

    
public   interface  IFactory    // 扩充工厂的通用接口
    {
        IIceBox CreateIceBox();  
// 生产冰箱
        IWasher CreateWasher();   // 生产洗衣机
    }

    
public   class  FactoryA : IFactory    // 扩充A型工厂
    {
        
public  IIceBox CreateIceBox()  // 生产A型冰箱
        {
        
return   new  IceBoxA();
        }

        
public  IWasher CreateWasher()  // 生产A型洗衣机
        {
        
return   new  IceBoxA();
        }
    }

    
public   class  FactoryB : IFactory   // 扩充B型工厂
    {
        
public  IIceBox CreateIceBox()  // 生产B型冰箱
        {
        
return   new  IceBoxB();
        }

        
public  IWasher CreateWasher()  // 生产B型洗衣机
        {
        
return   new  WasherB();
        }
    }

    
public   class  My
    {
        
private  IFactory factory  =   null // 注意:保存全局工厂实例,以便减少下次调用的实例化

        
private   void  GetFactory( string  Mode)
        {
        if  (Mode  ==   " A " ) factory  =   new  FactoryA();
        
else  factory  =   new  FactoryB();
        }

        
private   void  ShowInfo()
        {
        GetFactory(
" A " );
        IIceBox icebox 
=  factory.CreateIceBox();
        MessageBox.Show(icebox.FreezePower().ToString()); 
// 显示1,如上上一步换为"B",则显 示2

        IWasher washer 
=  factory.CreateWasher();
        MessageBox.Show(washer.WashPower().ToString()); 
// 洗涤能力:显示1,如前面换为"B",则 显示2
        }        
    }

这就是抽象工厂模式!
在.NET 2.0有一个抽象工厂模式的典型应用:通过DBProviderFactory 建立不同数据库类型的操作!
其基本对应关系如下:
1. DBProviderFactory 对应前面的 IFactory, 而具体的如SQLServer,Ocracle的DBProviderFactory对应前面

的FactoryA,FactoryB.
2. DBConnetion 对应 IIceBox, 而SQLConnetion,OracleConnection对应前面的IceBoxA,WasherA.
3. DBCommand 对应 IWasher,而SQLCommand,OracleCommand对应前面的IceBoxB,WasherB

具体类图以后一并补上!


不好意思,前一段没有完全说清楚工厂模式的具体用途,现补充如下:

总结:工厂模式的好处其实在于统一不同产品的访问接口!比如说我们在写数据库应用程序时,如果为SQL Server,则用SQLConnection,如为Oracle,则用OracleConnection.
一般在程序中写:SQLConnection conn = new SQLConnection(); 那如果要改为Oracle,则要重新改写并重编代码,但如果用工厂模式,则可以这样做:
DBProviderFactory factory = DBProviderFactorys.GetFactory("System.Data.SqlClient"); //可通过配置改变
DBConnection conn = factory.CreateConnection();
conn.ConnectionString = .....
也就达到了不用改动代码即实现更换不同数据库的目的!
 

http://www.cnblogs.com/yaozy/archive/2006/08/11/474732.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值