工厂方法模式(Factory Method)

来源:互联网 发布:软件详细设计工具 编辑:程序博客网 时间:2024/05/21 10:04

1. 模式定义

问题描述:

通常在导出数据上会有一些约定的格式,比如导出成文本格式,数据库备份形式,Excel格式,Xml格式。
对于实现数据导出的业务功能对象,它需要创建ExportFileApi的具体实现对象,但是它知道ExportFileApi接口,而不知道其具体的实现,那该怎么办?

工厂方法模式的定义:

定义一个用于创建对象的接口,让子类决定去实例化哪一个类,Factory Method使一个类的实现化延迟到其子类。

2. UML图

这里写图片描述
Product:定义工厂方法所创建的对象的接口,也就是实现需要使用的对象的接口
ConcreteProduct:Product的实现对象
Creator:声明工厂方法,工厂方法通常会返回一个Product类的实例对象,而且多是抽象方法
ConcreteCreator:覆盖实现Creator定义的工厂方法,返回具体的Product实例

具体代码:

/** * 导出的文件对象的接口 */public interface ExportFileApi {    /**     * 导出内容成为文件     * @param data 示意:需要保存的数据     * @return 是否导出成功     */    public boolean export(String data);}/** * 导出成数据库备份文件形式的对象 */public class ExportDB implements ExportFileApi{    public boolean export(String data) {        //简单示意一下,这里需要操作数据库和文件        System.out.println("导出数据"+data+"到数据库备份文件");        return true;    }}/** * 导出成文本文件格式的对象 */public class ExportTxtFile implements ExportFileApi{    public boolean export(String data) {        //简单示意一下,这里需要操作文件        System.out.println("导出数据"+data+"到文本文件");        return true;    }}/** * 实现导出数据的业务功能对象 */public abstract class ExportOperate {    /**     * 导出文件     * @param data 需要保存的数据     * @return 是否成功导出文件     */    public boolean export(String data){        //使用工厂方法        ExportFileApi api = factoryMethod();        return api.export(data);    }    /**     * 工厂方法,创建导出的文件对象的接口对象     * @return 导出的文件对象的接口对象     */    protected abstract ExportFileApi factoryMethod();}/** * 具体的创建器实现对象,实现创建导出成数据库备份文件形式的对象 */public class ExportDBOperate extends ExportOperate{    protected ExportFileApi factoryMethod() {        //创建导出成数据库备份文件形式的对象        return new ExportDB();    }}/** * 具体的创建器实现对象,实现创建导出成文本文件格式的对象 */public class ExportTxtFileOperate extends ExportOperate{    protected ExportFileApi factoryMethod() {        //创建导出成文本文件格式的对象        return new ExportTxtFile();    }}public class Client {    public static void main(String[] args) {        //创建需要使用的Creator对象        ExportOperate operate = new ExportDBOperate();        //调用输出数据的功能方法        operate.export("测试数据");    }}

3.研磨设计模式

工厂方法模式的功能主要是父类在不知道具体实现的情况下,完成自身的功能调用,而具体的实现让子类去做。

工厂方法的本质:延迟到子类去选择实现,有更好的维护性和可扩展性

一般不会把工厂方法暴露给客户端

IOC和DI

IOC Inversion Of Control 控制反转
DI Dependency Injection 依赖注入
依赖注入和控制反转是同一件事情的不同描述
依赖注入:从应用程序的角度描述,应用程序依赖容器创建并注入它所需要的外部资源;
控制反转:从容器的角度描述,容器控制应用程序,由容器反向地向程序注入其所需要的外部资源。
1. 参与者有谁:一个是某个Java对象,另一个是IOC/DI的容器,还有一个是某个对象的外部资源
2. 谁依赖于谁:某个Java对象依赖于IOC/DI的容器
3. 为什么需要依赖:对象需要IOC/DI容器来提供对象需要的外部资源
4. 谁注入谁:IOC/DI容器注入某个外部资源
5. 到底注入什么:注入某个对象所需的外部资源
6. 谁控制谁:IOC/DI的容器控制对象
7. 控制什么:控制对象实例的创建

参数化工厂方法值的是:通过给工厂方法传递参数,让工厂方法根据参数的不同创建不同的产品对象。

/** * 实现导出数据的业务功能对象 */public class ExportOperate {    /**     * 导出文件     * @param type 用户选择的导出类型     * @param data 需要保存的数据     * @return 是否成功导出文件     */    public boolean export(int type,String data){        //使用工厂方法        ExportFileApi api = factoryMethod(type);        return api.export(data);    }    /**     * 工厂方法,创建导出的文件对象的接口对象     * @param type 用户选择的导出类型     * @return 导出的文件对象的接口对象     */    protected ExportFileApi factoryMethod(int type){        ExportFileApi api = null;        //根据类型来选择究竟要创建哪一种导出文件对象        if(type==1){            api = new ExportTxtFile();        }else if(type==2){            api = new ExportDB();        }        return api;    }}public class Client {    public static void main(String[] args) {//      //创建需要使用的Creator对象//      ExportOperate operate = new ExportOperate();//      //调用输出数据的功能方法,传入选择到处类型的参数//      operate.export(1,"测试数据");        //创建需要使用的Creator对象        ExportOperate operate = new ExportOperate2();        //下面变换传入的参数来测试参数化工厂方法        operate.export(1,"Test1");        operate.export(2,"Test2");        operate.export(3,"Test3");    }}//扩展非常容易/** * 扩展ExportOperate对象,加入可以导出XML文件 */public class ExportOperate2 extends ExportOperate{    /**     * 覆盖父类的工厂方法,创建导出的文件对象的接口对象     * @param type 用户选择的导出类型     * @return 导出的文件对象的接口对象     */    protected ExportFileApi factoryMethod(int type){        ExportFileApi api = null;        //可以全部覆盖,也可以选择自己感兴趣的覆盖,        //这里只想添加自己新的实现,其他的不管        if(type==3){            api = new ExportXml();        }else{            //其他的还是让父类来实现            api = super.factoryMethod(type);         }        return api;     }}
0 0