`
chjavach
  • 浏览: 461056 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

研磨设计模式 之 生成器模式(Builder)1 ——跟着cc学设计系列

 
阅读更多

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)今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便的切换不同的输出格式的处理

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

可是该如何实现呢?

 


---------------------------------------------------------------------------

私塾在线学习网原创内容  跟着cc学设计系列 之 研磨设计模式

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/5084.html

---------------------------------------------------------------------------

6
2
分享到:
评论

相关推荐

    研磨设计模式(完整带书签).part2.pdf

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) ...

    研磨设计模式(完整带书签).part1.pdf

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) ...

    研磨设计模式-part2

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) ...

    研磨设计模式-part4

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) ...

    研磨设计模式-part3

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) ...

    研磨设计模式.part1(共4个)

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式...

    研磨设计模式.part3(共4个)

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式...

    研磨设计模式.part2(共4个)

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式...

    研磨设计模式.part4(共4个)

    第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式...

    DesignPattern

    《研磨设计模式》书中的例子 --第二章:简单工厂 本质:选择实现 --第三章:外观模式(Facade) 本质:封装交互,简化调用 --第四章:适配器模式(Adapter) 本质:转换匹配,复用功能 --第五章:单例模式(Singleton) ...

Global site tag (gtag.js) - Google Analytics