生成器模式

就这几天,花了两天辛辛苦苦写了一个导出数据的需求。换了好几种方案(在这之前我并没有看过生成器模式)。然后最终我把方案的实现定格在了策略模式。今天突然看到生成器模式,我在想,它们究竟有什么不同呢。

需求
先描述一下这个导出数据的需求:
Java Web项目,将数据库的某张表根据不同的条件将数据导出为不同格式的文件。比如Excel文件、CSV文件。
实现的基本步骤是:
读取需要导出的数据 –> 生成需要的格式 –> 将生成的对象写入本地磁盘 –> 读取本地磁盘文件上传至阿里云空间返回URL地址提供别人下载。
大致流程是这样的。
当时在不知道生成器模式的时候,换了好几种方案。最后将实现定格在了“策略模式”。
策略模式是:一群具有相同类型的对象,如果存在不同的行为,可以将这个行为独立出来,让每个对象依赖自己需要的行为。
我根据这一点,定义了一个ExportServer,提供了公共的方法:写入对象到磁盘、上传至阿里云空间并返回URL。然后读取数据分别由子类来实现(导出不同的表)。而生成需要的格式,依赖需要的行为。
大概结构:

public interface Action {
    T buildFile();
}

public class ExcelAction implements Action<Workbook> {
    public Workbook buildFile(){
        //封装Workbook
    }
}

pubilc class CSVAction implements Action<CSVPrint> {
    public CSVPrint buildFile(){
        //封装Workbook
    }
}


public abstract class ExportServer {
    public abstract T readData();

    public abstract Y buildWriter();

    public void dataToLocal(){
        //将已经构建好的File写在本地磁盘
    }

    public void uploadFileToOss(){
        //将本地文件上传至OSS(阿里云存储空间)
    }

}

public class EntityAExportServer extends ExportServer {
    //导出Excel文件。这个行为可以由外部传入,让调用者决定导出什么类型
    private Action action = new ExcelAction();

    public abstract EntityA readData(){
        //从数据库中获取数据
    }

    public Workbook buildWriter(){
        action.buildFile();
    }
}

public class EntityBExportServer extends ExportServer {
    //导出CSV文件
    private Action action = new CSVAction();

    public abstract EntityA readData(){
        //从数据库中获取数据
    }

    public CSVPrint buildWriter(){
        action.buildFile();
    }
}
//其他同理

public class Test {
    public static void main(String[] args){
        ExportServer exportServer = new EntityAExportServer();
        exportServer.readData();
        exportServer.buildWriter();
        exportServer.dataToLocal();
        exportServer.uploadFileToOss();
    }
}

当时的思路是在策略模式上面。感觉这个设计很完美。今天偶然看到了生成器模式。一开始的感觉是,这不就是策略模式么?

生成器模式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
这儿注意:同样的构建过程。
假设上面的需求,数据已经固定,根据这个数据,导出不同形式的文件。按照生成器的定义,构建过程与表示分离。
如果不使用模式,会这样写:

public class ExportExcel {
    public void buildFile(){
        //封装Excel文件对象
    }

    public void dataToLocal(){
        //将封装的文件对象写到本地
    }
    public void uploadFileToOss(){
        //将本地文件上传至阿里云存储空间
    }
}

public class ExportCSV {
    public void buildFile(){
        //封装CSV文件对象
    }

    public void dataToLocal(){
        //将封装的文件对象写到本地
    }
    public void uploadFileToOss(){
        //将本地文件上传至阿里云存储空间
    }
}

使用生成器,将buildFile独立出来。

public interfacce Build {
    void buildFile();
}

public class BuildExcel implements Build {
    public void buildFile(){
        //封装EXCEL文件对象
    }
}

public class BuildCSV implements Build {
    public void buildFile(){
        //封装CSV文件对象
    }
}

public class Export {
    build build;
    public Export(Build build){
        this.build = build;
    }
    public void buildFile(){
        build.buildFile();
    }

    public void dataToLocal(){
        //将封装的文件对象写到本地
    }
    public void uploadFileToOss(){
        //将本地文件上传至阿里云存储空间
    }
}

我一看生成器模式,不就是策略模式单个化了嘛。为什么要把它们分为两种不同的模式呢?
其实严格来说,我上面使用的那个所谓的“策略模式”,是一个“生成器模式”。策略模式的定义是,每一个子类的行为都是独立的,和他的其他行为没有相关联,是可以独立存在的。
例如动物类:
它们具有相同的行为是,可以吃饭,可以睡觉。不同的行为是:行走方式不同。小鸟飞着走,小猫小狗走着走,鱼儿虾类游着走,青蛙乌龟又能走又能游。这些不同的行为,和公有的行为是没有关联的。

而生成器模式:
构建与表示分离,生成需要的格式 –> 将生成的对象写入本地磁盘 –> 上传至阿里云空间。这个过程属于一个构建产品的过程,不同的生成方式,构建出来的产品不同。
生成器模式的主要功能是构建复杂产品,一个产品的构建过程是统一的,不变的,只是构建什么样的产品,将这个不同点独立在生成器中,只要配置不同的生成器,那么同样的构建过程,就能构建出不同的产品来。
整体来看,我还是很容易把这两种模式给混淆。如果非要我区分个哪是策略哪是生成器,我会根据他们的操作来区分。如果是一个对象的行为,则为策略模式。如果是一个对象的生成过程,则为生成器模式。

以上是个人对生成器模式与策略模式的理解与比较。也许有些地方写的很乱,不明白。如有大神有其他不同的理解,请多多评论指教。