zoukankan      html  css  js  c++  java
  • 工厂方法模式

    2018年8月22日19:34:48

    工厂方法模式

    定义

    吾欲娶卿,必问卿之父母,谓之父母之命。

    工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 ——《设计模式:可复用面向对象软件的基础》

    使用场景

    工厂方法模式在简单工厂模式的基础上,将判断逻辑的选择权上交给客户端,让客户端决定使用哪个具体工厂类。这算是工厂方法相比与简单工厂模式的缺点吧,这样的话,你就要事先知道有什么具体工厂类。相对于直白的new对象,不需要记住具体产品类,服务端隐藏了具体产品类的创建细节,在具体工厂类中不一定就是创建具体产品类,也可以做一些其他事情,符合面向对象的封装性。

    简单工厂模式加产品,需要修改内部判断逻辑,这是违反设计模式六大模式中的开闭原则,就是对扩展是开放的,对修改是关闭的。工厂方法模式加产品,只需增加相对应的具体工厂对象即可,符合开闭原则,这是工厂方法模式优点之一。个人观点:工厂方法模式适合那种经常更替(即增加和删除)具体产品对象的场景,正好利用了这个优点。如服装换季,你是一个设计师,换季了新的产品上架,加上新产品,老板选择新工厂,销售商家只需要从工厂获取新产品即可,旧产品下架,和旧工厂合同到期,就这样。

    角色

    将简单工厂模式的工厂角色内部逻辑判断上交给客户端后,分别封装创建对象细节到具体工厂类,具体工厂类都继承于一个共同的接口。简单工厂模式可查看:简单工厂模式

    工厂方法模式有以下四种角色:

    • 抽象工厂角色(IFactory):具体工厂公共接口,定义工厂方法返回产品
    • 具体工厂角色(ConcreteFactoryImpl):继承工厂工厂公共接口,实现工厂方法,运行期返回具体产品实例
    • 抽象产品角色(IProduct)
    • 具体产品角色(ConcreteProductImpl)

    图示

    工厂方法模式结构图

    代码示例

    代码示例依然用的是加减乘除运算操作,跟简单工厂模式一样,只是将工厂类SimpleFactory拆分为抽象工厂类和具体工厂类。简单工厂模式可查看:简单工厂模式

    类依赖关系图:
    工厂方法模式类依赖关系图

    抽象工厂角色(IOperationFactory.java):

    public interface IOperationFactory {
    	public IOperation createOperation();
    }
    

    抽象出来的具体工厂对象公共接口。

    具体工厂角色(AddOperationFactoryImpl.java、SubOperationFactoryImpl.java、MulOperationFactoryImpl.java、DivOperationFactoryImpl.java):

    // 加法工厂
    public class AddOperationFactoryImpl implements IOperationFactory {
    
    	@Override
    	public IOperation createOperation() {
    		return new AddOperationImpl();
    	}
    
    }
    // 减法工厂
    public class SubOperationFactoryImpl implements IOperationFactory {
    
    	@Override
    	public IOperation createOperation() {
    		return new SubOperationImpl();
    	}
    
    }
    //  乘法工厂
    public class MulOperationFactoryImpl implements IOperationFactory {
    
    	@Override
    	public IOperation createOperation() {
    		return new MulOperationImpl();
    	}
    
    }
    //  除法工厂
    public class DivOperationFactoryImpl implements IOperationFactory {
    
    	@Override
    	public IOperation createOperation() {
    		return new DivOperationImpl();
    	}
    
    }
    

    每个具体工厂对象对应一个具体产品对象。

    抽象产品角色(IProduct.java):

    public interface IOperation {
    	public int getResult(int a, int b);
    }
    

    具体产品角色(AddOperationImpl.java、SubOperationImpl.java、MulOperationImpl.java、DivOperationImpl.java):

    // 加法实现类
    public class AddOperationImpl implements IOperation{
    
    	@Override
    	public int getResult(int a, int b) {
    		return a + b;
    	}
    
    }
    // 减法实现类
    public class SubOperationImpl implements IOperation {
    	
    	@Override
    	public int getResult(int a, int b) {
    		return a - b;
    	}
    }
    // 乘法实现类
    public class MulOperationImpl implements IOperation {
    
    	@Override
    	public int getResult(int a, int b) {
    		return a * b;
    	}
    
    }
    // 除法实现类
    public class DivOperationImpl implements IOperation {
    
    	@Override
    	public int getResult(int a, int b) {
    		return a / b;
    	}
    
    }
    

    测试类(FactoryMethodTest.java):

    public class FactoryMethodTest {
    	
    	public static void main(String[] args) {
    		int a = 999, b = 888;
    		// 加
    		// 创建具体工厂
    		IOperationFactory operationFactory = new AddOperationFactoryImpl();
    		// 创建具体产品
    		IOperation operation = operationFactory.createOperation();
    		// 调用具体产品的功能
    		int result = operation.getResult(a, b); // 1887
    		System.out.println(result);
    		
    		// 减
    		operationFactory = new SubOperationFactoryImpl();
    		operation = operationFactory.createOperation();
    		result = operation.getResult(a, b); // 111
    		System.out.println(result);
    		
    		// 乘
    		operationFactory = new MulOperationFactoryImpl();
    		operation = operationFactory.createOperation();
    		result = operation.getResult(a, b); // 887112
    		System.out.println(result);
    		
    		// 除
    		operationFactory = new DivOperationFactoryImpl();
    		operation = operationFactory.createOperation();
    		result = operation.getResult(a, b); // 1
    		System.out.println(result);
    		
    	}
    	
    }
    

    客户端要判断使用什么具体工厂对象,从而实例化所需的具体产品对象。

    优点(小抄)

    (链接在文末参考处)

    1、在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

    2、基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。

    3、使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

    缺点(小抄)

    1、在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

    2、由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

    总结

    工厂方法模式是简单工厂模式的进一步抽象和推广。

    由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

    所有代码可见于Github.Mingmingcome

    参考:

    工厂方法模式(Factory Method Pattern)

  • 相关阅读:
    Git 基础
    SharePoint 2013 对象模型操作"网站设置"菜单
    SharePoint 2013 隐藏部分Ribbon菜单
    SharePoint 2013 Designer系列之数据视图筛选
    SharePoint 2013 Designer系列之数据视图
    SharePoint 2013 Designer系列之自定义列表表单
    SharePoint 2013 设置自定义布局页
    SharePoint 2013 "通知我"功能简介
    SharePoint 2013 创建web应用程序报错"This page can’t be displayed"
    SharePoint 禁用本地回环的两个方法
  • 原文地址:https://www.cnblogs.com/mingmingcome/p/9522007.html
Copyright © 2011-2022 走看看