第08章 雷锋依然在人间--工厂方法模式
8.2 简单工厂模式实现
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();
8.3 工厂方法模式实现
先构建一个工厂接口:
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();
8.4 简单工厂VS工厂方法
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但简单工厂不但对扩展开放,也对修改开放,这违背了开放封闭原则。
我们讲过,既然这个工厂类与分支耦合,那么我们就对他下手,根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,就变成了一个工厂抽象接口和多个具体生成对象的工厂,当我们需要增加新的功能时,就不需要更改原有的工厂类了,只需要增加此功能的运算类和相应的工厂类就可以了。
这样整个工厂和产品体系其实都没有修改的变化,而只是扩展的变化,这就完全符合了开放-封闭原则的精神。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移动到了客户端代码来运行。你想要加功能,本来是该工厂类的,而现在是修改客户端。
8.5 雷锋工厂
//雷锋
class LeiFeng
{
public void Sweep()
{
Console.WriteLine(“扫地”);
}
public void Wash()
{
Console.WriteLine(“洗衣”);
}
public void BuyRice()
{
Console.WriteLine(“买米”);
}
}
//学雷锋的大学生
class Undergraduate : LeiFeng
{ }
//客户端实现
Leiteng xueleifeng = new Undergraduate();
xueleifeng.BuyRice();
xueleifeng.Sweep();
xueleifeng.Wash();
//如果是有三个人学雷锋
Leiteng xueleifeng1 = new Undergraduate();
xueleifeng1.BuyRice();
Leiteng xueleifeng2 = new Undergraduate();
xueleifeng2.Sweep();
Leiteng xueleifeng3 = new Undergraduate();
xueleifeng3.Wash();
//社区志愿者
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();
现在如果需要修改的话只需要修改一处就可以了。利用反射技术可以做到更好。