简单工厂模式,用一句话概括其特性:使用子类继承并重写父类的方法,在实例化时,通过用户输入的参数,使用父类的实例化子类方法,返回相对应的子类,并访问该子类的属性及方法;
打个比方,我们去超市买可乐,有的人喜欢百事可乐,有的人喜欢可口可乐,那我们买可乐的过程用代码表示出来是什么样的?看看下面的代码:
/// <summary>
/// 可口可乐
/// </summary>
public class KeKou
{
public string KeLe()
{
return "I'm KeKouKeLe";
}
}
/// <summary>
/// 可口可乐
/// </summary>
public class BaiShi
{
public string KeLe()
{
return "I'm BaiShiKeLe";
}
}
那么我们在超市里面买可乐的过程用代码表示出来应该是什么样的?我想应该是这样的:
//购买百事可乐的过程
BaiShi baiShi = new BaiShi();
string keLe = baiShi.KeLe();
//购买可口可乐的过程
KeKou keKou = new KeKou();
string keLe = keKou.KeLe();
通过上面的代码,我们分别拿到了百事可乐和可口可乐;
忽然有一天我们出差了,要买可乐,但是在外面找不到超市,只有自动售贩机,这下习惯在超市买东西的同志们犯难了,以前可以直接把东西拿出来,现在不行了,只能通过售贩机帮你取出来,经过研究,发现自动售贩机的使用流程是这样的:先把钱投到售贩机里面,如果我们要百事可乐,就按1号键,如果我们要可口可乐,就按2号键,这个流程怎么表示出来呢?我想应该是下面这样的:
![](http://hi.csdn.net/attachment/201111/10/0_1320896563byLV.gif)
我们告诉售贩机需要什么样的可乐,售贩机将我们需要的可乐吐出来;我想实现的代码应该是下面的样子:
/// <summary>
/// 可乐
/// </summary>
public class Cola
{
public virtual string KeLe()
{
return "I'm KeLe";
}
public Cola GetKeLe(int index)
{
switch (index)
{
case 1:
return new BaiShi();
default :
return new KeKou();
}
}
}
下面的百事和可口继承可乐,代码如下:
/// <summary>
/// 可口可乐
/// </summary>
public class KeKou:Cola
{
public override string KeLe()
{
return "I'm KeKouKeLe";
}
}
/// <summary>
/// 百事可乐
/// </summary>
public class BaiShi:Cola
{
public override string KeLe()
{
return "I'm BaiShiKeLe";
}
}
那么客户端的代码应该为:
Cola cola = new Cola();
cola = cola.GetKeLe(1);
cola.KeLe();
上面的代码是不是很别扭?首先实例化了一个Cola类,然后将该实例的指向转为cola.GetKeLe(1),这里是简单工厂需要注意的地方之一:Cola cola = new Cola()代码实例化了一个Cola对象,该对象拥有的是Cole的属性和方法,与子类没有任何关系,所以此时通过cola访问不到任何与子类相关的内容;cola = cola.GetKeLe(1)代码实际上做了两件事情,首先是根据用户输入的参数实例化子类,然后将cola实例的指向转到刚才生成的子类上,所以此时即可通过cola访问子类的相关内容;
上面说到了这么写难看,那么我们怎么改一下?代码如下:
/// <summary>
/// 可乐工厂
/// </summary>
public class Cola
{
public virtual string KeLe()
{
return "I'm KeLe";
}
public static Cola GetKeLe(int index)
{
switch (index)
{
case 1:
return new BaiShi();
default:
return new KeKou();
}
}
}
上面的代码只是在工厂类的创建对象方法上添加了一个关键字:static,使这个方法变为静态方法,同时改变了该方法的访问模式:通过类可以直接访问该方法,而不需要通过类的实例访问;修改后我们再看看客户端上应该怎样访问:
Colacola = Cola.GetKeLe(1);
cola.KeLe();
上面的代码不仅更符合逻辑,也更贴近真实的情况;
另外在简单工厂方法中还有一点需要注意,父类的方法必须提供为虚方法,继承父类的子类对父类虚方法进行重写,我们来看看下面的代码:
父类:
/// <summary>
/// 可乐工厂
/// </summary>
public class Cola
{
public virtual string KeLe()
{
return "I'm KeLe";
}
public static Cola GetKeLe(int index)
{
switch (index)
{
case 1:
return new BaiShi();
default:
return new KeKou();
}
}
}
子类:
/// <summary>
/// 可口可乐
/// </summary>
public class KeKou : Cola
{
public new string KeLe()
{
return "I'm KeKouKeLe";
}
}
/// <summary>
/// 可口可乐
/// </summary>
public class BaiShi : Cola
{
public new string KeLe()
{
return "I'm BaiShiKeLe";
}
}
此时通过客户端代码访问:
Colacola = Cola.GetKeLe(1);
cola.KeLe();
得到的解决是我们访问了父类中的方法,这里需要弄清楚两个关键字的用途:new和override;
Msdn上这么解释的,new:用于向基类成员隐藏继承成员;override:修饰符用于重写基类中方法的方法,当基类不包含具有相同签名的成员时,不得将 override 修饰符用于方法;