工厂方法模式
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
简单工厂模式的优缺点
简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
但是如果要加一个功能,就需要修改原有的类,增加Case分支,这违背了开放-封闭原则。
将简单工厂模式改进为工厂方法模式
根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法就是创建抽象产品的工厂方法。然后所有的要生产具体类的工厂就去实现这个接口。
当我们要增加功能时就不需要更改原有的工厂类了,只需要增加此功能的类和相应的工厂就可以了。
工厂方法模式需要让客户端决定实例化哪个一个工厂来实现类
也就是说工厂方法把简单工厂的内部逻辑判断移动到了客户端代码来进行。你想要增加功能本来是改工厂类的,而现在是修改客户端。
改进简单计算器
工厂接口:IFactory
interface IFactory{ Operation CreateOperation(); }
加减乘除各建一个具体工厂去实现这个接口
class AddFactory : IFactory{ public Operation CreateOperation => new OperationAdd(); } class SubFactory : IFactory{ public Operation CreateOperation => new OperationSub(); } class MulFactory : IFactory{ public Operation CreateOperation => new OperationMul(); } class DivFactory : IFactory{ public Operation CreateOperation => new OperationDiv(); }
测试类:Program
IFactory operFactory = new AddFactory(); Operation oper = operFactory.CreateOperation; oper.NumbleA = 1; oper.NumbleB = 2; Console.WriteLine(oper.GetResult());//结果:3
雷锋工厂
雷锋类:LeiFeng
class LeiFeng{ public void Sweep() => Console.WriteLine("扫地"); public void Wash() => Console.WriteLine("洗衣"); public void BuyRice() => Console.WriteLine("买米"); }
学雷锋的大学生类:Undergraduate
class Undergraduate : LeiFeng { }
社区志愿者类:Volunteer
class Volunteer : LeiFeng { }
雷锋工厂类:IFactory
interface IFactory{ LeiFeng CreateLeiFeng(); }
学雷锋的大学生工厂:UndergraduateFactory
class UndergraduateFactory : IFactory{ public LeiFeng CreateLeiFeng() => new Undergraduate(); }
社区志愿者工厂:VolunteerFactory
class VolunteerFactory : IFactory{ public LeiFeng CreateLeiFeng() => new Volunteer(); }
测试类:Program
//Main方法 IFactory factory = new UndergraduateFactory(); LeiFeng student = factory.CreateLeiFeng(); student.BuyRice(); student.Sweep(); student.Wash(); //测试结果 买米 扫地 洗衣
总结
工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。
工厂方法模式是简单工厂模式的进一步抽象。
缺点是每加一个产品就需要加一个产品工厂的类,增加了额外的开发量。
利用反射可以解决客户端修改分支判断的代码。