`

builder模式1

 
阅读更多

8.1  场景问题

8.1.1  继续导出数据的应用框架

在讨论工厂方法模式的时候,提到了一个导出数据的应用框架。

对于导出数据的应用框架,通常在导出数据上,会有一些约定的方式,比如导出成:文本格式、数据库备份形式、Excel格式、Xml格式等等。

在工厂方法模式章节里面,讨论并使用工厂方法模式来解决了如何选择具体导出方式的问题,并没有涉及到每种方式具体如何实现。

换句话说,在讨论工厂方法模式的时候,并没有讨论如何实现导出成文本、Xml等具体的格式,本章就来讨论这个问题。

对于导出数据的应用框架,通常对于具体的导出内容和格式是有要求的,假如现在有如下的要求,简单描述一下:

  • 导出的文件,不管什么格式,都分成三个部分,分别是文件头、文件体和文件尾
  • 在文件头部分,需要描述如下信息:分公司或门市点编号、导出数据的日期,对于文本格式,中间用逗号分隔
  • 在文件体部分,需要描述如下信息:表名称、然后分条描述数据。对于文本格式,表名称单独占一行,数据描述一行算一条数据,字段间用逗号分隔。
  • 在文件尾部分,需要描述如下信息:输出人

现在就要来实现上述功能。为了演示简单点,在工厂方法模式里面已经实现的功能,这里就不去重复了,这里只关心如何实现导出文件,而且只实现导出成文本格式和XML格式就可以了,其它的就不去考虑了。

8.1.2  不用模式的解决方案

       不就是要实现导出数据到文本文件和XML文件吗,其实不管什么格式,需要导出的数据是一样的,只是具体导出到文件中的内容,会随着格式的不同而不同。

(1)先来把描述文件各个部分的数据对象定义出来,先看描述输出到文件头的内容的对象,示例代码如下:

/**

 * 描述输出到文件头的内容的对象

 */

public class ExportHeaderModel {

    /**

     * 分公司或门市点编号

     */

    private String depId;

    /**

     * 导出数据的日期

     */

    private String exportDate;

    public String getDepId() {

       return depId;

    }

    public void setDepId(String depId) {

       this.depId = depId;

    }

    public String getExportDate() {

       return exportDate;

    }

    public void setExportDate(String exportDate) {

       this.exportDate = exportDate;

    }

}

接下来看看描述输出数据的对象,示例代码如下:

/**

 * 描述输出数据的对象

 */

public class ExportDataModel {

    /**

     * 产品编号

     */

    private String productId;

    /**

     * 销售价格

     */

    private double price;

    /**

     * 销售数量

     */

    private double amount;

   

    public String getProductId() {

       return productId;

    }

    public void setProductId(String productId) {

       this.productId = productId;

    }

    public double getPrice() {

       return price;

    }

    public void setPrice(double price) {

       this.price = price;

    }

    public double getAmount() {

       return amount;

    }

    public void setAmount(double amount) {

       this.amount = amount;

    }

}

接下来看看描述输出到文件尾的内容的对象,示例代码如下:

/**

 * 描述输出到文件尾的内容的对象

 */

public class ExportFooterModel {

    /**

     * 输出人

     */

    private String exportUser;

    public String getExportUser() {

       return exportUser;

    }

    public void setExportUser(String exportUser) {

       this.exportUser = exportUser;

    }

}

(2)接下来具体的看看导出的实现,先看导出数据到文本文件的对象,主要就是要实现拼接输出的内容,示例代码如下:

/**

 * 导出数据到文本文件的对象

 */

public class ExportToTxt {

    /**

     * 导出数据到文本文件

     * @param ehm 文件头的内容

     * @param mapData 数据的内容

     * @param efm 文件尾的内容

     */

    public void export(ExportHeaderModel ehm

,Map<String,Collection<ExportDataModel>> mapData

,ExportFooterModel efm){

       //用来记录最终输出的文件内容

       StringBuffer buffer = new StringBuffer();

       //1:先来拼接文件头的内容

       buffer.append(ehm.getDepId()+","

+ehm.getExportDate()+"\n");

       //2:接着来拼接文件体的内容

       for(String tblName : mapData.keySet()){

           //先拼接表名称

           buffer.append(tblName+"\n");

           //然后循环拼接具体数据

           for(ExportDataModel edm : mapData.get(tblName)){

              buffer.append(edm.getProductId()+","

+edm.getPrice()+","+edm.getAmount()+"\n");

           }

       }

       //3:接着来拼接文件尾的内容

       buffer.append(efm.getExportUser());

      

       //为了演示简洁性,这里就不去写输出文件的代码了

       //把要输出的内容输出到控制台看看

       System.out.println("输出到文本文件的内容:\n"+buffer);

    }

}

(3)接下来看看导出数据到XML文件的对象,比较麻烦,要按照XML的格式进行拼接,示例代码如下:

/**

 * 导出数据到XML文件的对象

 */

public class ExportToXml {

    /**

     * 导出数据到XML文件

     * @param ehm 文件头的内容

     * @param mapData 数据的内容

     * @param efm 文件尾的内容

     */

    public void export(ExportHeaderModel ehm

,Map<String,Collection<ExportDataModel>> mapData

,ExportFooterModel efm){

       //用来记录最终输出的文件内容

       StringBuffer buffer = new StringBuffer();

       //1:先来拼接文件头的内容

       buffer.append(

"<?xml version='1.0' encoding='gb2312'?>\n");

       buffer.append("<Report>\n");

       buffer.append("  <Header>\n");

       buffer.append("    <DepId>"+ehm.getDepId()+"</DepId>\n");

       buffer.append("    <ExportDate>"+ehm.getExportDate()

+"</ExportDate>\n");

       buffer.append("  </Header>\n");

       //2:接着来拼接文件体的内容

       buffer.append("  <Body>\n");

       for(String tblName : mapData.keySet()){

           //先拼接表名称

           buffer.append(

"    <Datas TableName=\""+tblName+"\">\n");

           //然后循环拼接具体数据

           for(ExportDataModel edm : mapData.get(tblName)){

              buffer.append("      <Data>\n");

              buffer.append("        <ProductId>"

+edm.getProductId()+"</ProductId>\n");

              buffer.append("        <Price>"+edm.getPrice()

+"</Price>\n");

              buffer.append("        <Amount>"+edm.getAmount()

+"</Amount>\n");

              buffer.append("      </Data>\n");

           }

           buffer.append("    </Datas>\n");

       }

       buffer.append("  </Body>\n");

       //3:接着来拼接文件尾的内容

       buffer.append("  <Footer>\n");

       buffer.append("    <ExportUser>"+efm.getExportUser()

+"</ExportUser>\n");

       buffer.append("  </Footer>\n");

       buffer.append("</Report>\n");

      

       //为了演示简洁性,这里就不去写输出文件的代码了

       //把要输出的内容输出到控制台看看

       System.out.println("输出到XML文件的内容:\n"+buffer);

    }

}

(4)看看客户端,如何来使用这些对象,示例代码如下:

public class Client {

    public static void main(String[] args) {

       //准备测试数据

       ExportHeaderModel ehm = new ExportHeaderModel();

       ehm.setDepId("一分公司");

       ehm.setExportDate("2010-05-18");

      

       Map<String,Collection<ExportDataModel>> mapData =

new HashMap<String,Collection<ExportDataModel>>();

       Collection<ExportDataModel> col =

new ArrayList<ExportDataModel>();

      

       ExportDataModel edm1 = new ExportDataModel();

       edm1.setProductId("产品001号");

       edm1.setPrice(100);

       edm1.setAmount(80);

      

       ExportDataModel edm2 = new ExportDataModel();

       edm2.setProductId("产品002号");

       edm2.setPrice(99);

       edm2.setAmount(55);     

       //把数据组装起来

       col.add(edm1);

       col.add(edm2);      

       mapData.put("销售记录表", col);

      

       ExportFooterModel efm = new ExportFooterModel();

       efm.setExportUser("张三");     

       //测试输出到文本文件

       ExportToTxt toTxt = new ExportToTxt();

       toTxt.export(ehm, mapData, efm);

       //测试输出到xml文件

       ExportToXml toXml = new ExportToXml();

       toXml.export(ehm, mapData, efm);

    }

}

运行结果如下:

输出到文本文件的内容:

一分公司,2010-05-18

销售记录表

产品001号,100.0,80.0

产品002号,99.0,55.0

张三

输出到XML文件的内容:

<?xml version='1.0' encoding='gb2312'?>

<Report>

  <Header>

    <DepId>一分公司</DepId>

    <ExportDate>2010-05-18</ExportDate>

  </Header>

  <Body>

    <Datas TableName="销售记录表">

      <Data>

        <ProductId>产品001号</ProductId>

        <Price>100.0</Price>

        <Amount>80.0</Amount>

      </Data>

      <Data>

        <ProductId>产品002号</ProductId>

        <Price>99.0</Price>

        <Amount>55.0</Amount>

      </Data>

    </Datas>

  </Body>

  <Footer>

    <ExportUser>张三</ExportUser>

  </Footer>

</Report>

8.1.3  有何问题

仔细观察上面的实现,会发现,不管是输出成文本文件,还是输出到XML文件,在实现的时候,步骤基本上都是一样的,都大致分成了如下四步:

  • 先拼接文件头的内容
  • 然后拼接文件体的内容
  • 再拼接文件尾的内容
  • 最后把拼接好的内容输出出去成为文件

也就是说,对于不同的输出格式,处理步骤是一样的,但是具体每步的实现是不一样的。按照现在的实现方式,就存在如下的问题:

(1)构建每种输出格式的文件内容的时候,都会重复这几个处理步骤,应该提炼出来,形成公共的处理过程

(2)今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便的切换不同的输出格式的处理

换句话来说,也就是构建每种格式的数据文件的处理过程,应该和具体的步骤实现分开,这样就能够复用处理过程,而且能很容易的切换不同的输出格式。

可是该如何实现呢?

分享到:
评论

相关推荐

    Penglq#book-1#Builder模式1

    Builder模式模式介绍模式的定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。Android源码中的模式实现在Android源码

    (创建型模式)Builder模式

    1. **模块化构建**:Builder模式允许我们在不修改已有代码的情况下,添加新的构建步骤或改变现有步骤的顺序,增强了代码的灵活性。 2. **复杂对象的构建**:对于拥有众多属性和复杂构建过程的对象,Builder模式可以...

    设计模式-Builder模式demo

    Builder模式是一种创建型设计模式,它提供了一种创建对象的抽象接口,并允许子类按照步骤构建复杂的对象。这种模式将对象的创建过程分离出来,使得同样的构造过程可以创建不同的表示,从而实现对象创建过程的解耦。 ...

    Builder模式

    1. 当需要生成的产品对象有复杂的内部结构时,使用Builder模式可以将构建过程分解为一系列小步骤,便于管理和控制。 2. 当产品对象的属性之间存在依赖关系时,Builder模式可以确保正确的构建顺序,避免因属性设置...

    设计模式 创建型模式 Builder模式(建造者)

    Builder模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 统设计中,有时候面临着一个“复杂系统”的创建工作,该对象通常由各个部分的子对象用一定的算法构成,或者说按一定的...

    builder设计模式源码

    1. **Product(产品类)**:这是Builder模式所创建的对象。在这个例子中,Product可能是一个复杂的对象,比如一个软件应用程序或硬件设备的配置。它定义了产品的公共接口,确保所有Builder生成的对象都符合这个接口...

    Maple-Chan#Maple-Chan.Blog#2020-11-23-Builder模式1

    介绍UserBuilder builder = new UserBuilder();User user = builder.builder();可以通过上述代码

    设计模式之建造者Builder模式

    **建造者模式(Builder Pattern)**是软件设计模式中的一种,属于创建型模式。它将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通常用于那些需要大量构造参数的对象,通过...

    Builder模式在Java中的应用

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成。那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Builder模式来替代多参数...

    BUILDER模式 C++实现

    Builder模式是一种设计模式,它属于创建型模式,主要用于复杂对象的构建。在C++中,Builder模式可以帮助我们分步骤地创建一个复杂的对象,而无需关注这些步骤如何组合在一起。这样可以使得构造过程更加灵活,同时也...

    创建型——Builder模式

    Builder模式是一种创建型设计模式,它提供了一种创建对象的灵活方式,将对象的构建过程与表示分离。这种模式在复杂对象的构造过程中特别有用,因为它允许我们通过不同的步骤来构造对象,而不会让客户端代码受到这些...

    Builder 模式

    Builder模式是一种设计模式,它属于创建型模式,主要用于构建复杂对象。这种模式允许我们通过分离对象的构造过程和表示来创建对象,使得构造过程可以更加灵活,并且能够避免在构造过程中对对象状态的直接修改。...

    (设计模式)Builder

    在给定的博客链接中,可能详细讨论了如何在实际项目中应用Builder模式,例如在软件开发工具或框架中,通过Builder模式来构建数据结构或配置对象。Builder模式能够帮助开发者将对象的创建过程分解为一系列步骤,使得...

    【Java面试题】builder模式

    【Java面试题】builder模式

    设计模式之创建模式Builder

    建造者模式(Builder Pattern)是设计模式中的一种创建型模式,它允许我们分步骤构建复杂的对象,而无需暴露其构造过程。这种模式的核心思想在于将对象的构建与表示分离,使得构建过程和不同表示可以独立变化,提高...

    builder设计模式

    Builder模式的核心组成部分包括: 1. **产品类(Product)**:这是要构建的复杂对象。Product类通常有多个组成部件,例如ProductPart。在给定的例子中,`product.cpp`和`productpart.cpp`可能包含了这些类的定义。 ...

    Builder模式Demo

    Builder模式是一种设计模式,它属于创建型模式,主要用于复杂对象的构建。在Builder模式中,一个Builder类会一步一步构造所创建的对象。用户可以对建造过程逐步控制,而不必关心对象内部细节,从而使得构建过程更加...

    生成器模式builder

    Builder模式属于创建型设计模式,它的核心思想是将对象的创建过程与对象本身分离,使得同样的构建过程可以创建不同的表示。 在Java或其他面向对象语言中,生成器模式通常包括四个主要角色:产品(Product)、建造者...

    软件体系结构Builder模式浅谈

    Builder模式是一种设计模式,主要目的是将复杂对象的构建与表示分离,使得构建过程可以独立于表示进行。在软件工程中,当需要创建的对象具有多个可变组成部分时,Builder模式能够帮助我们构造这些对象,同时保持构建...

    晨会分享Builder设计模式

    文件可能还包含了Builder模式与其他设计模式(如工厂模式、抽象工厂模式)的对比,以及如何在Java、C#等编程语言中使用Builder模式的示例代码。通过学习这个文件,可以深入理解Builder模式,并掌握如何在项目中有效...

Global site tag (gtag.js) - Google Analytics