• 工厂方法模式2


    2  解决方案

    2.1  工厂方法模式来解决

            用来解决上述问题的一个合理的解决方案就是工厂方法模式。那么什么是工厂方法模式呢?
    (1)工厂方法模式定义
            定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。

    (2)应用工厂方法模式来解决的思路
            仔细分析上面的问题,事实上在实现导出数据的业务功能对象里面,根本就不知道究竟要使用哪一种导出文件的格式,因此这个对象本就不应该和具体的导出文件的对象耦合在一起,它只需要面向导出的文件对象的接口就好了。
            但是这样一来,又有新的问题产生了:接口是不能直接使用的,需要使用具体的接口实现对象的实例。
            这不是自相矛盾吗?要求面向接口,不让和具体的实现耦合,但是又需要创建接口的具体实现对象的实例。怎么解决这个矛盾呢?
            工厂方法模式的解决思路很有意思,那就是不解决,采取无为而治的方式:不是需要接口对象吗,那就定义一个方法来创建;可是事实上它自己是不知道如何创建这个接口对象的,没有关系,那就定义成抽象方法就好了,自己实现不了,那就让子类来实现,这样这个对象本身就可以只是面向接口编程,而无需关心到底如何创建接口对象了。


    2.2  模式结构和说明

            工厂方法模式的结构如图3所示:


                         图3  工厂方法模式结构示意图


    Product
            定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。
    ConcreteProduct:
            具体的Product接口的实现对象。
    Creator:
            创建器,声明工厂方法,工厂方法通常会返回一个Product类型的实例对象,而且多是抽象方法。也可以在Creator里面提供工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象。
    ConcreteCreator:
            具体的创建器对象,覆盖实现Creator定义的工厂方法,返回具体的Product实例。


    2.3  工厂方法模式示例代码

    (1)先看看Product的定义,示例代码如下:

    /**

     * 工厂方法所创建的对象的接口

     */

    public interface Product {

        //可以定义Product的属性和方法

    }


    (2)再看看具体的Product的实现对象,示例代码如下: 

    /**

     * 具体的Product对象

     */

    public class ConcreteProduct implements Product {

        //实现Product要求的方法

    }

    (3)接下来看看创建器的定义,示例代码如下: 

    /**

     * 创建器,声明工厂方法

     */

    public abstract class Creator {

        /**

         * 创建Product的工厂方法

         * @return Product对象

         */

        protected abstract Product factoryMethod();

        /**

         * 示意方法,实现某些功能的方法

         */

        public void someOperation() {

           //通常在这些方法实现中,需要调用工厂方法来获取Product对象

           Product product = factoryMethod();

        }

    }

    (4)再看看具体的创建器实现对象,示例代码如下: 

    /**

     * 具体的创建器实现对象

     */

    public class ConcreteCreator extends Creator {

        protected Product factoryMethod() {

           //重定义工厂方法,返回一个具体的Product对象

           return new ConcreteProduct();

        }

    }

    2.4  使用工厂方法模式来实现示例

            要使用工厂方法模式来实现示例,先来按照工厂方法模式的结构,对应出哪些是被创建的Product,哪些是Creator。分析要求实现的功能,导出的文件对象接口ExportFileApi就相当于是Product,而用来实现导出数据的业务功能对象就相当于Creator。把Product和Creator分开过后,就可以分别来实现它们了。
            使用工厂模式来实现示例的程序结构如图4所示:


                                     图4  使用工厂模式来实现示例的程序结构示意图
     下面一起来看看代码实现。
    (1)导出的文件对象接口ExportFileApi的实现没有变化,这里就不去赘述了
    (2)接下来看看接口ExportFileApi的实现,为了示例简单,只实现导出文本文件格式和数据库备份文件两种。先看看导出文本文件格式的实现,示例代码如下: 

    /**

     * 导出成文本文件格式的对象

     */

    public class ExportTxtFile implements ExportFileApi{

        public boolean export(String data) {

           //简单示意一下,这里需要操作文件

           System.out.println("导出数据"+data+"到文本文件");

           return true;

        }

    }

    再看看导出成数据库备份文件形式的对象的实现,示例代码如下:  

    /**

     * 导出成数据库备份文件形式的对象

     */

    public class ExportDB implements ExportFileApi{

        public boolean export(String data) {

           //简单示意一下,这里需要操作数据库和文件

           System.out.println("导出数据"+data+"到数据库备份文件");

           return true;

        }

    }

    (3)Creator这边的实现,首先看看ExportOperate的实现,示例代码如下: 

    /**

     * 实现导出数据的业务功能对象

     */

    public abstract class ExportOperate {

        /**

         * 导出文件

         * @param data 需要保存的数据

         * @return 是否成功导出文件

         */

        public boolean export(String data){

           //使用工厂方法

           ExportFileApi api = factoryMethod();

           return api.export(data);

        }

        /**

         * 工厂方法,创建导出的文件对象的接口对象

         * @return 导出的文件对象的接口对象

         */

        protected abstract ExportFileApi factoryMethod();

    }

    (4)加入了两个Creator实现,先看看创建导出成文本文件格式的对象,示例代码如下:  

    /**

     * 具体的创建器实现对象,实现创建导出成文本文件格式的对象

     */

    public class ExportTxtFileOperate extends ExportOperate{

        protected ExportFileApi factoryMethod() {

           //创建导出成文本文件格式的对象

           return new ExportTxtFile();

        }

    }

    再看看创建导出成数据库备份文件形式的对象,示例代码如下:  

    /**

     * 具体的创建器实现对象,实现创建导出成数据库备份文件形式的对象

     */

    public class ExportDBOperate extends ExportOperate{

        protected ExportFileApi factoryMethod() {

           //创建导出成数据库备份文件形式的对象

           return new ExportDB();

        }

    }

    (5)客户端直接创建需要使用的Creator对象,然后调用相应的功能方法,示例代码如下:  

    public class Client {

        public static void main(String[] args) {

           //创建需要使用的Creator对象

           ExportOperate operate = new ExportDBOperate();

           //调用输出数据的功能方法

           operate.export("测试数据");

        }

    }

    运行结果如下:  

    导出数据测试数据到数据库备份文件

             你还可以修改客户端new的对象,切换成其它的实现对象,试试看会发生什么。看来应用工厂方法模式是很简单的,对吧。

  • 相关阅读:
    数据仓库-(3)企业级数仓实战分享课程-1.课程简介/2.数仓简介/3.基础概念/4.大数据技术栈与组件
    数据仓库-(2)企业级数仓介绍
    数据仓库-(1)数仓主题分享记录
    Spark学习小记-(1)DataFrame的schema
    Hive学习小记-(11)left semi join
    Hive学习小记-(10)hive增量下发的变化流水表如何做update操作
    Hive学习小记-(9)hive分区表加字段**
    Hive学习小记-(8)hive查询除某列外所有数据(正则表达式查询)
    Hive学习小记-(7)group by原理&tips
    我曾七次鄙视自己的灵魂
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1759913.html
Copyright © 2020-2023  润新知