有这样一个场景,假设我是一家电器生产公司职员,主要工作是从设计部那里拿到设计好的图纸,然后交给生产部门进行生产,再对生产好的产品进行相关的检测.需要做一套系统来显示测试的结果.
刚开始公司只生产一种型号的冰箱,需要检测的是冰箱的冷冻能力.那我们可能会这样实现:
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 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
}
}
}
{
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型冰箱,扩充也更容易!其实这就叫简单工厂模式!{
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
}
}
不过随着公司规模的扩大,又新建了一个工厂,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,改动也不大!这就是工厂模式!{
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
}
}
不过随着公司规模进一步扩大,出现了这样的需求:
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
}
}
这就是抽象工厂模式!{
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 = .....
也就达到了不用改动代码即实现更换不同数据库的目的!