《设计模式》—工厂方法模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述工厂方法模式的:

  工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。

  工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。

那么工厂方法模式是在什么场景下使用呢,下面就以本人的理解举例说明:

  相信很多人都做过导入导出功能,就拿导出功能来说。有这么一个需求:XX系统需要支持对数据库中的员工薪资进行导出,并且支持多种格式如:HTML、CSV、PDF等,每种格式导出的结构有所不同,比如:财务跟其他人对导出薪资的HTML格式要求可能会不一样,因为财务可能需要特定的格式方便核算或其他用途。

  如果使用简单工厂模式,则工厂类必定过于臃肿。因为简单工厂模式只有一个工厂类,它需要处理所有的创建的逻辑。假如以上需求暂时只支持3种导出的格式以及2种导出的结构,那工厂类则需要6个if else来创建6种不同的类型。如果日后需求不断增加,则后果不堪设想。

  这时候就需要工厂方法模式来处理以上需求。在工厂方法模式中,核心的工厂类不再负责所有的对象的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个类应当被实例化这种细节。

  这种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品,这一特点无疑使得工厂方法模式具有超过简单工厂模式的优越性。下面就针对以上需求设计UML图:

  从上图可以看出,这个使用的工厂方法模式的系统涉及到以下角色:

  抽象工厂(ExportFactory)角色:担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。在实际的系统中,这个角色也常常使用抽象类实现。

  具体工厂(ExportHtmlFactory、ExportPdfFactory)角色:担任这个角色的是实现了抽象工厂接口的具体JAVA类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建导出类(如:ExportStandardHtmlFile)。

  抽象导出(ExportFile)角色:工厂方法模式所创建的对象的超类,也就是所有导出类的共同父类或共同拥有的接口。在实际的系统中,这个角色也常常使用抽象类实现。

  具体导出(ExportStandardHtmlFile等)角色:这个角色实现了抽象导出(ExportFile)角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体导出角色的实例。

源代码

  首先是抽象工厂角色源代码。它声明了一个工厂方法,要求所有的具体工厂角色都实现这个工厂方法。参数type表示导出的格式是哪一种结构,如:导出HTML格式有两种结构,一种是标准结构,一种是财务需要的结构。

public interface ExportFactory {
    public ExportFile factory(String type);
}

  具体工厂角色类源代码:

public class ExportHtmlFactory implements ExportFactory{
    @Override
    public ExportFile factory(String type) {
        // TODO Auto-generated method stub
        if("standard".equals(type)){

            return new ExportStandardHtmlFile();

        }else if("financial".equals(type)){

            return new ExportFinancialHtmlFile();

        }else{
            throw new RuntimeException("没有找到对象");
        }
    }

}
public class ExportPdfFactory implements ExportFactory {

    @Override
    public ExportFile factory(String type) {
        // TODO Auto-generated method stub
        if("standard".equals(type)){

            return new ExportStandardPdfFile();

        }else if("financial".equals(type)){

            return new ExportFinancialPdfFile();

        }else{
            throw new RuntimeException("没有找到对象");
        }
    }

}

  抽象导出角色类源代码:

public interface ExportFile {
    public boolean export(String data);
}

  具体导出角色类源代码,通常情况下这个类会有复杂的业务逻辑。

public class ExportFinancialHtmlFile implements ExportFile{
    @Override
    public boolean export(String data) {
        // TODO Auto-generated method stub
        /**
         * 业务逻辑
         */
        System.out.println("导出财务版HTML文件");
        return true;
    }

}
public class ExportFinancialPdfFile implements ExportFile{
    @Override
    public boolean export(String data) {
        // TODO Auto-generated method stub
        /**
         * 业务逻辑
         */
        System.out.println("导出财务版PDF文件");
        return true;
    }
}
public class ExportStandardHtmlFile implements ExportFile{
    @Override
    public boolean export(String data) {
        // TODO Auto-generated method stub
        /**
         * 业务逻辑
         */
        System.out.println("导出标准HTML文件");
        return true;
    }

}
public class ExportStandardPdfFile implements ExportFile {
    @Override
    public boolean export(String data) {
        // TODO Auto-generated method stub
        /**
         * 业务逻辑
         */
        System.out.println("导出标准PDF文件");
        return true;
    }
}

客户端角色类源代码:

public class Test {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String data = "";
        ExportFactory exportFactory = new ExportHtmlFactory();
        ExportFile ef = exportFactory.factory("financial");
        ef.export(data);
    }
}

工厂方法模式的活动序列图

  客户端创建ExportHtmlFactory对象,这时客户端所持有变量的静态类型为ExportFactory,而实际类型为ExportHtmlFactory。然后客户端调用ExportHtmlFactory对象的工厂方法factory(),接着后者调用ExportFinancialHtmlFile的构造子创建出导出对象。

工厂方法模式和简单工厂模式

  工厂方法模式和简单工厂模式在结构上的不同很明显。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

  工厂方法模式退化后可以变得很像简单工厂模式。设想如果非常确定一个系统只需要一个具体工厂类,那么不妨把抽象工厂类合并到具体工厂类中去。由于只有一个具体工厂类,所以不妨将工厂方法改为静态方法,这时候就得到了简单工厂模式。

  如果系统需要加入一个新的导出类型,那么所需要的就是向系统中加入一个这个导出类以及所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的导出类型而言,这个系统完全支持“开-闭原则”。

  

完结

  一个应用系统是由多人开发的,导出的功能是你实现的,但是使用者(调用这个方法的人)可能却是其他人。这时候你应该设计的足够灵活并尽可能降低两者之间的耦合度,当你修改或增加一个新的功能时,使用者不需要修改任何地方。假如你的设计不够灵活,那么将无法面对客户多变的需求。可能一个极小的需求变更,都会使你的代码结构发生改变,并导致其他使用你所提供的接口的人都要修改他们的代码。牵一处而动全身,这就使得日后这个系统将难以维护。

时间: 2024-08-01 01:28:06

《设计模式》—工厂方法模式的相关文章

C#设计模式——工厂方法模式

一.引言 在简单工厂中讲到简单工厂模式的缺点,有一点是--简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以解决简单工厂模式中存在的这个问题,下面就具体看看工厂模式是如何解决该问题的. 二.工厂方法模式的实现 工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创建推迟到子类中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式就可以允许系统不修改工厂类逻辑的

工厂方法模式

开放-封闭原则: 在设计模式中,对于不能修改,但可以扩展的思想也是一种重要的设计原则.比如国家对于香港的一国两制.大陆的社会主义是不可以更改的,但由于香港长期处于资本主义下,强制执行社会主义难免有些牵强,所以邓小平同志就用了开放-封闭原则,完美的解决了这一问题.在前期进行软件设计的时候,应该做好后期新增需求的准备.尽量做到新增需求时,不需要更改已有代码,而是新增代码,进行需求的扩展. 工厂方法模式: 问题抛出:在上一篇文章中,通过一个简单的两位数计算介绍了简单工厂模式.在这基础上,试想如果我们需

Java设计模式—工厂方法模式&抽象工厂模式

工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式.       工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义:Creator为抽象创建 类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的. 工厂方法模式的扩展方式有很多种,下边是工厂方法模式一个比较实用的源代码: 抽象产品类: pub

java语言实现创建型设计模式—工厂方法模式

一.描述 基于简单工厂模式中将所有类的创建和初始化放在一个工厂类中出现的问题,我们引进了工厂方法模式,该模式是GoF总结的23种设计模式的第一种,这个设计模式将一个工厂类拆分成多个具体的工厂类,每个具体的工厂类负责相应的类的对象的创建. 在工厂方法模式中,抽象工厂类负责定义创建对象的接口,具体对象的创建由实现该抽象工厂的具体工厂类来完成,它由四部分组成:抽象工厂类.实现抽象工厂类的具体工厂类.抽象类.实现抽象类的具体类. 二.工厂方法模式的优缺点 优点:在工厂方法模式中,创建对象的任务由具体的工

设计模式三:工厂方法模式

疑惑解答: 1.interface接口不能够实例化(new),但是可以定义引用来指向继承该接口的实体类: 如: interface animal{ void eat(); } class Cat implements animal{ public void eat(){ System.out.println("The cat eat!"); } } animal an = new Cat(); 一.什么是工厂方法模式 1.是简单工厂模式的进一步抽象: 2.定义一个创建产品对象的工厂接口

大话设计模式-第八章-工厂方法模式

一.UML图 二.包含的角色 (1)抽象工厂 (2)具体工厂 (3)抽象产品 (4)具体产品 三.优势 (1)工厂方法模式是对简单工厂模式的稍微的改进.工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中. (2)与简单工厂模式相比,制造产品的工厂类不再 只有一个,而是每种具体产品类都对应一个生产它的具体工厂类.而这些具体工厂类的共同特征再被提取出来形成一个抽象产品类,这些具体产品类都继承自这个抽象产品类. (3)当需要增加一种产品的时候,需要做的是:增加一种继承自抽象产品

Java设计模式菜鸟系列(四)工厂方法模式建模与实现

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39760895 工厂方法模式(Factory Method) 工厂方法:顾名思义,就是调用工厂里的方法来生产对象(产品)的. 工厂方法实现方式有3种: 一.普通工厂模式.就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 1.uml建模图: 2.代码实现 /** * 示例(一):普通工厂方法 * * 缺点:如果传递的字符串出错,则不能正确创建对象 */ interface Sen

JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象. 在这些情况,新对象的建立就是一个 "过程",不仅是一个操作,像一部大机器中的一个齿轮传动. 模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实

设计模式5:工厂方法模式

在之前提到的简单方法模式中,如果需要给计算器添加一种运算,需要增加一个Operation子类,然后修改工厂类. 这样的设计一方面简化了客户端的修改,另一方面需要修改工厂类,这是违反开放-封闭模式的. 处理这种问题的另一种方法是工厂方法模式. 工厂方法模式克服了违反开放-封闭的缺点,同时保持了封装对象创建过程的优点,但是带来的缺点是,需要新增一个工厂类+修改客户端代码以实现功能扩展. 来看UML图: 四种运算的子类是继承了Operation基类,每个子类都有一个对应的工厂类,封装了创建其实例的过程

单例模式和工厂方法模式

单例模式的定义 单例模式(Singleton Pattern)是一个比较简单的模式,其定义如下: Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.) 单例模式通用代码 public class Singleton { private static final Singleton singleton = new Sin