研磨设计模式 之 生成器模式(Builder)1 ——跟着cc学设计系列
在讨论工厂方法模式的时候,提到了一个导出数据的应用框架。
对于导出数据的应用框架,通常在导出数据上,会有一些约定的方式,比如导出成:文本格式、数据库备份形式、Excel格式、Xml格式等等。
在工厂方法模式章节里面,讨论并使用工厂方法模式来解决了如何选择具体导出方式的问题,并没有涉及到每种方式具体如何实现。
换句话说,在讨论工厂方法模式的时候,并没有讨论如何实现导出成文本、Xml等具体的格式,本章就来讨论这个问题。
对于导出数据的应用框架,通常对于具体的导出内容和格式是有要求的,假如现在有如下的要求,简单描述一下:
现在就要来实现上述功能。为了演示简单点,在工厂方法模式里面已经实现的功能,这里就不去重复了,这里只关心如何实现导出文件,而且只实现导出成文本格式和XML格式就可以了,其它的就不去考虑了。
?????? 不就是要实现导出数据到文本文件和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>
仔细观察上面的实现,会发现,不管是输出成文本文件,还是输出到XML文件,在实现的时候,步骤基本上都是一样的,都大致分成了如下四步:
也就是说,对于不同的输出格式,处理步骤是一样的,但是具体每步的实现是不一样的。按照现在的实现方式,就存在如下的问题:
(1)构建每种输出格式的文件内容的时候,都会重复这几个处理步骤,应该提炼出来,形成公共的处理过程
(2)今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便的切换不同的输出格式的处理
换句话来说,也就是构建每种格式的数据文件的处理过程,应该和具体的步骤实现分开,这样就能够复用处理过程,而且能很容易的切换不同的输出格式。
可是该如何实现呢?
?
---------------------------------------
私塾在线学习网原创内容 ?跟着cc学设计系列 之?研磨设计模式
原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/5084.html】
---------------------------------------