工厂方法模式

2019-07-29  本文已影响0人  闽越布衣

描述

    工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
    工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。

简介

工厂方法类图

    工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

    工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

    工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

角色

优缺点

优点

    创建对象的接口,让子类决定具体实例化的对象,把简单的内部逻辑判断移到了客户端。工厂方法模式克服了简单工厂所违背的开闭原则的缺点,又保持了封装对象创建过程的优点。
    扩展性高,想要增加一个产品,只要扩展一个工厂类以及对应的产品类就可以。

缺点

    在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
    由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

使用场景

示例

    我们拿导出功能来说。有这么一个需求:XX系统需要支持对数据库中的员工薪资进行导出,并且支持多种格式如:HTML、CSV、PDF等,每种格式导出的结构有所不同,比如:财务跟其他人对导出薪资的HTML格式要求可能会不一样,因为财务可能需要特定的格式方便核算或其他用途。
    如果使用简单工厂模式,则工厂类必定过于臃肿。因为简单工厂模式只有一个工厂类,它需要处理所有的创建的逻辑。假如以上需求暂时只支持3种导出的格式以及2种导出的结构,那工厂类则需要6个if else来创建6种不同的类型。如果日后需求不断增加,则后果不堪设想。

/**
* 抽象工厂角色
*/
public interface ExportFactory {
    ExportFile factory(String type);
}
/**
* 具体工厂(ExportHtmlFactory)角色
*/
public class ExportHtmlFactory implements ExportFactory {
    private final String STANDARD = "STANDARD";
    private final String FINANCIAL = "FINANCIAL";

    @Override
    public ExportFile factory(String type) {
        if (STANDARD.equals(type)) {
            return new ExportStandardHtmlFile();
        } else if (FINANCIAL.equals(type)) {
            return new ExportFinancialHtmlFile();
        } else {
            throw new RuntimeException("没有找到对象");
        }
    }
}
/**
* 具体工厂(ExportPdfFactory)角色
*/
public class ExportPdfFactory implements ExportFactory {
    private final String STANDARD = "STANDARD";
    private final String FINANCIAL = "FINANCIAL";

    @Override
    public ExportFile factory(String type) {
        if (STANDARD.equals(type)) {
            return new ExportStandardPdfFile();
        } else if (FINANCIAL.equals(type)) {
            return new ExportFinancialPdfFile();
        } else {
            throw new RuntimeException("没有找到对象");
        }
    }
}
/**
* 抽象产品角色
*/
public interface ExportFile {
    boolean export(String data);
}
/**
* 具体产品(ExportStandardHtmlFile)角色
*/
public class ExportStandardHtmlFile implements ExportFile {
    @Override
    public boolean export(String data) {
        /**
         * 处理逻辑
         */
        System.out.println("导出标准HTML");
        return true;
    }
}
/**
* 具体产品(ExportStandardPdfFile)角色
*/
public class ExportStandardPdfFile implements ExportFile {
    @Override
    public boolean export(String data) {
        /**
         * 处理逻辑
         */
        System.out.println("导出标准PDF");
        return true;
    }
}
/**
* 具体产品(ExportFinancialHtmlFile)角色
*/
public class ExportFinancialHtmlFile implements ExportFile {
    @Override
    public boolean export(String data) {
        /**
         * 处理逻辑
         */
        System.out.println("导出财务版HTML");
        return true;
    }
}
/**
* 具体产品(ExportFinancialPdfFile)角色
*/
public class ExportFinancialPdfFile implements ExportFile {
    @Override
    public boolean export(String data) {
        /**
         * 处理逻辑
         */
        System.out.println("导出财务版PDF");
        return true;
    }
}

上一篇下一篇

猜你喜欢

热点阅读