一、 工厂方法(Factory Method)模式
工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化那一个类。工厂方法使一个类的实例化延迟至其子类。因为简单工厂模式一定程度上会违背开方-封闭的原则,但工厂方法由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点,工厂方法模式是简单工厂模式的进一步抽象与推广,还有工厂方法更复杂的层次结构,可以应用于产品结果复杂的场合。
在工厂方法模式中,核心的工厂类不再负责产品的创建,而是把具体的创建工作交给子类去完成。核心的工厂类只负责给出具体工厂必须实现的接口,而不会去接触,实例化任何一个产品。这使得工厂访求模式可以允许系统在不修改工厂角色的情况下引进新产品。
二、 工厂方法模式的角色与结构:
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
结构图:
三、简单工厂与工厂方法的区别
简单工厂最大的优点在于简单工厂包含必要的逻辑判断,根据客户端的条件动态的实例化相关的类,对于客户端来说,去除了具体产品的依赖。
工程方法模式(Factory Mode)定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延长到其子类。
四、工厂方法的实例
下面用一个实例来说明一下工厂方法。在简单工厂模式用过写windows 计算器的应用(例子源于<<大话设计模式>>)。假如现在需要给计算器添加一个M的N次方的计算方式时,就要在原来的运算工厂类添加M的N次的判断分支。这违背了"开放-封闭"原则,那么在简单工厂的基础上,做进一步的推广,把它修改成工厂方法模式。
计算器的UML图:
运算工厂类不再实例化计算类的对象,而把实例化的工作交给其子类,运算工厂类只负责给出具体运算必须实现的接口。
部分代码:
/// <summary> /// 运算类 /// </summary> class Operation { private double _numberA = 0; private double _numberB = 0; public double NumberA { get { return _numberA; } set { _numberA = value; } } public double NumberB { get { return _numberB; } set { _numberB = value; } } /// <summary> /// 得到运算结果 /// </summary> /// <returns></returns> public virtual double GetResult() { double result = 0; return result; } }
/// <summary> /// 加法类 /// </summary> class OperationAdd : Operation { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } } /// <summary> /// 减法类 /// </summary> class OperationSub : Operation { public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } } /// <summary> /// 乘法类 /// </summary> class OperationMul : Operation { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } } /// <summary> /// 除法类 /// </summary> class OperationDiv : Operation { public override double GetResult() { double result = 0; if (NumberB == 0) throw new Exception("除数不能为0。"); result = NumberA / NumberB; return result; } }
/// <summary> /// 工厂方法 /// </summary> interface IFactory { Operation CreateOperation(); }
/// <summary> /// 专门负责生产“+”的工厂 /// </summary> class AddFactory : IFactory { public Operation CreateOperation() { return new OperationAdd(); } } /// <summary> /// 专门负责生产“-”的工厂 /// </summary> class SubFactory : IFactory { public Operation CreateOperation() { return new OperationSub(); } } /// <summary> /// 专门负责生产“*”的工厂 /// </summary> class MulFactory : IFactory { public Operation CreateOperation() { return new OperationMul(); } } /// <summary> /// 专门负责生产“/”的工厂 /// </summary> class DivFactory : IFactory { public Operation CreateOperation() { return new OperationDiv(); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 工厂方法模式 { class Program { static void Main(string[] args) { IFactory operFactory = new AddFactory(); Operation oper = operFactory.CreateOperation(); oper.NumberA = 1; oper.NumberB = 2; double result = oper.GetResult(); Console.WriteLine(result); Console.Read(); } } }