理解工厂方法模式需要与简单工厂模式对比来看,先来对比一下利用两种模式实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果.
简单工厂模式实现
//简单工厂模式工厂类
public class OperationFactory
{
public static Operation createOperate(string operate)
{
Operation oper = null;
switch (operate)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
}
return oper;
}
}
//客户端实现
Operation oper;
oper = OperationFactory.createOperate("+");
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();
工厂方法模式实现
//工厂接口
interface IFactory
{
Operation CreateOperation();
}
//对于加减乘除各建一个具体的工厂去实现接口
class AddFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationAdd();
}
}
class SubFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationSub();
}
}
class MulFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationMul();
}
}
class DivFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationDiv();
}
}
//客户端实现
IFactory operFactory = new AddFactory();
Operation oper = operFactory.CreateOperation();
oper.NumberA = 1;
oper.NumberB = 2;
double result=oper.GetResult();
上面两种实现反映了简单工厂模式和工厂方法模式的区别,疑问在于,如果需要添加新的运算方法,好像工厂方法模式要更为复杂,不光需要增加功能类,增加工厂类,甚至还要去修改客户端。那使用工厂方法模式的意义在哪里?
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是,考虑增加运算功能,对于简单工厂模式需要修改原有类,这违反了开放-封闭原则。这时候工厂方法模式就有存在的必要了。
简单工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工厂方法实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。
再来通过一个实现的例子来说明工厂方法模式。
问题描述:实现大学生和社区志愿者学习雷锋做好事的过程。
简单工厂模式实现
//雷锋类
class LeiFeng
{
public void Sweep()
{
Console.WriteLine("扫地");
}
public void Wash()
{
Console.WriteLine("洗衣");
}
public void BuyRice()
{
Console.WriteLine("买米");
}
}
//大学生类
class Undergraduate : LeiFeng
{ }
//社区志愿者类
class Volunteer : LeiFeng
{ }
//简单工厂类
class SimpleFactory
{
public static LeiFeng CreateLeiFeng(string type)
{
LeiFeng result = null;
switch (type)
{
case "学雷锋的大学生":
result = new Undergraduate();
break;
case "社区志愿者":
result = new Volunteer();
break;
}
return result;
}
}
//客户端代码
LeiFeng studentA = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentA.BuyRice();
LeiFeng studentB = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentB.Sweep();
LeiFeng studentC = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentC.Wash();
工厂方法模式实现
//工厂类
interface IFactory
{
LeiFeng CreateLeiFeng();
}
//大学生工厂类
class UndergraduateFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Undergraduate();
}
}
//社区志愿者工厂类
class VolunteerFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Volunteer();
}
}
//客户端代码
IFactory factory = new UndergraduateFactory();
LeiFeng student = factory.CreateLeiFeng();
student.BuyRice();
student.Sweep();
student.Wash();
可以看到,上述两种客户端如果修改,工厂方法模式要修改的地方要少。工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。可以说,工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态,工厂方法模式保持了简单工厂模式的优点,而且克服了其缺点,缺点是没增加一个产品,都需要加一个产品工厂的类,增加了额外的开放量。
参考书籍:《大话设计模式》