工厂方法模式:
简单工厂 VS 工厂方法(以计算器为例):
简单工厂UML结构图:
工厂方法UML结构图:
简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是我们增加新功能时,我们一定要修改工厂类中的Case分支条件,这样就不满足开放——封闭原则了。
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法模式使一个类的实例化延迟到了其子类。
工厂方法模式UML结构图:
这样整个工厂和产品体系其实都没有修改的变化,而只是拓展的变化,这样就完全符合了开放封闭原则,但是实际问题还是存在的,我们不能避免实际实例化工厂过程中的选择问题,工厂方法模式把简单工厂的内部逻辑判断移到了客户端代码进行,即你想要的功能,本来是修改工厂类的,现在是修改客户端。(以学雷锋助老人为例,本来只有大学生这一类功能,如果要添加社会志愿者,那么对于工厂模式来说我们需要修改工厂类Case然后创建社区志愿者类,对于工厂方法模式来说,我们要扩展社区志愿者工厂然后创建社区志愿者,但是实例化对象时,我们需要先在客户端完成创建社区志愿者子类工厂然后决定实例化,即由修改工厂变成修改客户端)
例:工厂模式:
//简单雷锋工厂
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;
}
//简单工厂模式Client 三句重复的代码:
LeiFeng studentA = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentA.BuyRice();
LeiFeng studentB = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentB.Sweep();
LeiFeng studentC = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentC.Wash();
//如果创建Volunteer社区志愿者对象的话直接修改字符串即可:
LeiFeng volunteer = SimpleFactory.CreateLeiFeng("社区志愿者");
volunteer.Wash();
工厂方法模式:
//雷锋工厂
interface IFactory
{
LeiFeng CreateLeiFeng();
}
//学雷锋的大学生工厂
class UndergraduateFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Undergraduate();
}
}
//社区志愿者工厂
class VolunteerFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Volunteer();
}
}
//工厂方法模式Client
IFactory factory = new UndergraduateFactory();
LeiFeng student = factory.CreateLeiFeng();
student.BuyRice();
student.Sweep();
student.Wash();
工厂方法模式克服了简单工厂违背开放——封闭原则的缺点,同时又保持了封装对象创建过程的优点,使得要更换对象时不需要做大的改动就可以实现,降低了客户端程序与产品的耦合,工厂方法模式是简单工厂模式的进一步抽象和推广(但是缺点就是每增加一个产品,就增加一个产品工厂的子类,增加了额外的开发量)。