工厂模式
现在,如果我想要创建一个界面View的实例需要调用View的构造函数:View view=new View();
现在我想要创建3个不同的界面,分别是View1,View2,View3,那么我将在另一个类中调用它们的构造函数。
View1 view1 = new View1(); View2 view2 = new View2(); View3 view3 = new View3();
如果有更多的窗口呢?这样公开的使用new操作符,很容易造成耦合问题。但若创建实例就必须使用new,那么我们如何更好的使用new呢?
简单工厂
其实我们再平时写代码时或许已经有了这样的思想。这许多的View都有很多共同点,假设其中一个便是显示窗口的名称(当然这没有什么实际意义),我们将其抽象为一个接口IView,为了方便,这里的View就是单纯的类,不是真正意义上的Window.
public interface IView { void Display(); }
public class View1 : IView { public void Display() { System.Console.WriteLine("界面1"); } }
public class View2 : IView { public void Display() { System.Console.WriteLine("界面2"); } }
public class View3 : IView { public void Display() { System.Console.WriteLine("界面3"); } }
然后我们把所有实例的创建都放在ViewFactory中:
public class ViewFactory { public ViewFactory() { } public static IView CreateView(string viewName) { switch (viewName) { case "View1": return new View1(); case "View2": return new View2(); case "View3": return new View3(); default: return null; } } }
这样便可按需(根据View的名字作为参数)创建实例,并调用显示名称的方法:
class Program { static void Main(string[] args) { ViewFactory.CreateView("View1").Display(); ViewFactory.CreateView("View2").Display(); ViewFactory.CreateView("View3").Display(); System.Console.ReadLine(); } }
运行结果:
上面这个就是典型的简单工厂模式了,其实我们平时可能已经有了这样的思想,只是并没有进行更多的总结。通过简单工厂,我们将所有实例化封进另外一个对象,同时通过多态实现了针对接口的编程,而不是直接针对具体类View1等。
如果此时,我还想再增加View4等等,我不仅需要增加View4的界面,还必须修改ViewFactory,增加几句代码:
case "View4": return new View4();
增加新界面就必须修改ViewFactory,这明显违背了开-闭原则,这也是简单工厂模式的缺点。
工厂方法模式
由于简单工厂违背了开闭原则,需要在简单工厂的基础上修改一下,就是工厂方法模式(Factory Method),与简单工厂不同的是,创建对象不会集中在同一个类中,而是通过FactoryMethod方法在各个子类中分别实现相应对象的实例。
每个View都会有自己独立的Factory,现在将这多个Factory抽象为接口IFactory:
public interface IFactory { IView GetView(); }
各个独立的Factory,可取得对应的对象实例:
public class ViewFactory1 : IFactory { public IView GetView() { return new View1(); } }
public class ViewFactory2 : IFactory { public IView GetView() { return new View2(); } }
调用,只以View1为例:
class Program { static void Main(string[] args) { IFactory factory = new ViewFactory1(); IView view = factory.GetView(); view.Display(); System.Console.ReadLine(); } }
结果:
如果需要新增一个View4,需要增加一个ViewFactory4和View4的类,但是不必修改已存在的其他类。
抽象工厂
提供一个创建一系列相关或者事相互依赖对象的接口,而无需指定它们具体的类。
也就是说具体工厂生产类似的产品(这些产品继承自统一父类),每一个具体工厂可产生多种产品.比如,我这里的一个抽象工厂可产生窗口和控件,红色工厂可产生红色的View和Control,绿色工厂可产生绿色的View和Control,但红绿工厂产生的View都继承自IView,Control继承自IControl。
public abstract class AbstractFactory { public abstract IView CreateView(); public abstract IControl CreateControl(); }
以具体绿工厂为例:
public class GreenFactory : AbstractFactory { public override IView CreateView() { return new GreenView(); } public override IControl CreateControl() { return new GreenControl(); } }
public class GreenView : IView { public void Display() { System.Console.WriteLine("绿色窗口"); } }
public class GreenControl : IControl { public void Display() { System.Console.WriteLine("我是 绿色工厂 生产出来的 绿色 控件。"); } }
红色工厂类似我就不再贴出代码了,直接看一下调用:
class Program { static void Main(string[] args) { AbstractFactory.AbstractFactory factoryG = new GreenFactory(); IView viewG = factoryG.CreateView(); viewG.Display(); IControl controlG = factoryG.CreateControl(); controlG.Display(); System.Console.WriteLine(); AbstractFactory.AbstractFactory factoryR = new RedFactory(); IView viewR = factoryR.CreateView(); viewR.Display(); IControl controlR = factoryR.CreateControl(); controlR.Display(); System.Console.ReadLine(); } }
运行结果:
简单工厂&工厂方法对比:
简单工厂 | 工厂方法 | 抽象工厂 |
所有实例化在同一个类中实现,将对象封装 | 创建一个接口,让子类决定如何实现 | |
对象被封装,违背开闭原则,弹性弱 | 将实例化延迟到子类 | 易膨胀,过于臃肿 |
参考链接:http://www.cnblogs.com/BoyXiao/archive/2010/05/06/1728808.html