在使用面向对象编程时,我们都说遵循一个基本准则------开放封闭原则;即对于软件实体(类、模块、函数等)应该可以扩展,但是不能修改,也就是对于扩展是开放的,对于更改是封闭的;
依据这个原则,我们接着上面的可乐说事儿,此时市场上出现了第三种可乐:非常可乐;我们应该怎么修改贩卖机的程序呢?
修改起来也不复杂,我们看看修改的代码:
首先在子类列表中新增一个非常可乐的类,
/// <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";
}
}
/// <summary>
/// 非常可乐
/// </summary>
public class FeiChang : Cola
{
public override string KeLe()
{
return "I'm FeiChangKeLe";
}
}
然后呢?此时我们需要修改可乐工厂的代码了,修改后代码如下:
/// <summary>
/// 可乐工厂
/// </summary>
public class Cola
{
public virtual string KeLe()
{
return "I'm KeLe";
}
public static Cola GetCola(int index)
{
switch (index)
{
case 1:
return new BaiShi();
case 2:
return new KeKou();
default:
return new FeiChang();
}
}
}
我们看到,这里我们在swith的分支中新增了一个生成非常可乐的分支;功能满足了,但是返回来再想想,我们这么做是不是违反了封闭开放原则呢?封闭开放原则的中心思想就是在面对需求变化时,只通过增加代码来满足需求,而不是修改现有的代码;那么这里是不是还有地方可以抽象出来的呢?
先看看在上面的简单工厂模式中客户端的访问代码:
Colacola = Cola.GetCola(3);
cola.KeLe();
这里产生修改主要是由于需要工厂判断产出哪种可乐;如果这些工作由客户端来进行会是怎么样的呢?我想代码应该是这样的:
Cola cola =factroy.GetBaiShiCola();
cola.KeLe();
也就是说,我们希望有一个工厂专门生产百事可乐,有一个工厂专门生产可口可乐,那么我们抽象出来,我想代码应该是这样的:
首先公开一个可乐工厂的接口,规定所有工厂必须生产可乐!
/// <summary>
/// 工厂接口
/// </summary>
public interface IKeLeFactroy
{
Cola GetCola();
}
下面分别声明百事、可口等可乐的可乐工厂,代码如下:
/// <summary>
/// 百事工厂
/// </summary>
public class BaiShiFactroy : IKeLeFactroy
{
public Cola GetCola()
{
return new BaiShi();
}
}
/// <summary>
/// 可口工厂
/// </summary>
public class KeKouFacyroy : IKeLeFactroy
{
public Cola GetCola()
{
return new KeKou();
}
}
/// <summary>
/// 非常可乐工厂
/// </summary>
public class FeiChang : IKeLeFactroy
{
public Cola GetCola()
{
return new FeiChang();
}
}
那么客户端的访问代码如下:
IKeLeFactroy factroy = new BaiShiFactroy();
Cola cola = factroy.GetCola();
cola.KeLe();
如果此时我们需要新增可乐种类怎么办?
第一步:我们需要建立新增的可乐类;
第二部:我们需要建立该类的工厂;OK,搞定;
下面我们看看工厂方法模式的UML图:
![](http://hi.csdn.net/attachment/201111/10/0_1320898375mM4a.gif)