工厂方法模式:

简单工厂 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();

工厂方法模式克服了简单工厂违背开放——封闭原则的缺点,同时又保持了封装对象创建过程的优点,使得要更换对象时不需要做大的改动就可以实现,降低了客户端程序与产品的耦合,工厂方法模式是简单工厂模式的进一步抽象和推广(但是缺点就是每增加一个产品,就增加一个产品工厂的子类,增加了额外的开发量)。