@@@模式定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
@@@练习示例:
继续工厂方法模式中的导出数据的应用框架。
@@@示例代码:
\export\ExportHeaderModel.java
\export\ExportDataModel.java
\export\ExportFooterModel.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\export\ExportToTxt.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\export\ExportToXml.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------------------------------------
不使用模式时存在的问题 :
对于不同的输出格式,处理步骤是一样的,但是每步的具体实现是不一样的。
构建每种输出格式的文件内容时,都会重复这几个处理步骤,应该提炼出来,形成公共的处理过程。
今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便地切换不同的输出格式的处理。
构建每种格式的数据文件的处理过程,应该和具体的步骤实现分开,
这样就能够复用处理过程,而且能很容易地切换不同的输出格式。
-------------------------------------------------------------
\export\Builder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\export\TxtBuilder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\export\XmlBuilder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\export\Director.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\user\Client2.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@@模式的实现:
1. 生成器中的每个方法可以有两部分的功能,一部分是创建部件对象,另一部分是组装部件。
2. 指导者承担的是整体构建算法部分,是相对不变的。
3. 产品构建过程中,指导者和生成器之间可能会存在比较复杂的交互过程。
4. 客户端最终从Builder实现里面获取最终装配好的产品。
5. 一般不需要对产品定义抽象接口,因为最终构建出来的产品千差万别。
@@@模式的功能:
生成器模式的主要功能是构建复杂的产品,而且是细化的、分步骤地构建产品,
也就是生成器模式重在一步一步解决构造复杂对象的问题。
更重要的是,这个构建的过程是统一的、固定不变的,变化的部分放到生成器部分了,只要配置不同的生成器,
那么同样的构建过程,就能构建出不同的产品来。
@@@模式的构成:
1. Builder接口,定义了如何构建各个部件,如何装配产品。
2. Director,定义了使用部件装配产品的步骤。
@@@模式的优点:
1. 松散耦合。
2. 可以很容易地改变产品的内部表示。
3. 更好的复用性
@@@模式的缺点:
无
@@@模式的本质:
分离整体构建算法和部件构造过程。
@@@模式体现的设计原则:
无
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
@@@练习示例:
继续工厂方法模式中的导出数据的应用框架。
@@@示例代码:
\export\ExportHeaderModel.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
/**
* 描述输出到文件头的内容的类
*/
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;
}
}
\export\ExportDataModel.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
/**
* 描述输出数据的类
*/
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;
}
}
\export\ExportFooterModel.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
/**
* 描述输出到文件尾的内容的类
*/
public class ExportFooterModel {
/**
* 输出人
*/
private String exportUser;
public String getExportUser() {
return exportUser;
}
public void setExportUser(String exportUser) {
this.exportUser = exportUser;
}
}
\export\ExportToTxt.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 导出数据到文本文件的类
*/
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);
}
}
\export\ExportToXml.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 导出数据到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);
}
}
\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package user;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import export.ExportDataModel;
import export.ExportFooterModel;
import export.ExportHeaderModel;
import export.ExportToTxt;
import export.ExportToXml;
public class Client {
public static void main(String[] args) {
// 准备测试数据
ExportHeaderModel ehm = new ExportHeaderModel();
ehm.setDepId("一分公司");
ehm.setExportDate("2013-06-02");
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(108);
edm2.setAmount(56);
// 把数据组装起来
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);
}
}
-------------------------------------------------------------
不使用模式时存在的问题 :
对于不同的输出格式,处理步骤是一样的,但是每步的具体实现是不一样的。
构建每种输出格式的文件内容时,都会重复这几个处理步骤,应该提炼出来,形成公共的处理过程。
今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便地切换不同的输出格式的处理。
构建每种格式的数据文件的处理过程,应该和具体的步骤实现分开,
这样就能够复用处理过程,而且能很容易地切换不同的输出格式。
-------------------------------------------------------------
\export\Builder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 生成器接口,定义创建一个输出文件对象所需的各个部件的操作
*/
public interface Builder {
/**
* 构建输出文件的Header部分
* @param ehm 文件头的内容
*/
public void buildHeader(ExportHeaderModel ehm);
/**
* 构建输出文件的Body部分
* @param mapData 要输出的数据的内容
*/
public void buildBody(Map<String, Collection<ExportDataModel>> mapData);
/**
* 构建输出文件的Footer部分
* @param efm 文件尾的内容
*/
public void buildFooter(ExportFooterModel efm);
}
\export\TxtBuilder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 实现导出数据到文本文件的具体生成器类
*/
public class TxtBuilder implements Builder {
/**
* 用来记录构建的文件的内容,相当于产品
*/
private StringBuffer buffer = new StringBuffer();
@Override
public void buildHeader(ExportHeaderModel ehm) {
buffer.append(ehm.getDepId() + ", " + ehm.getExportDate() + "\n");
}
@Override
public void buildBody(Map<String, Collection<ExportDataModel>> mapData) {
for (String tblName : mapData.keySet()) {
// 先拼接表名称
buffer.append(tblName + "\n");
// 然后循环拼接具体数据
for (ExportDataModel edm : mapData.get(tblName)) {
buffer.append(edm.getProductId() + ", " +
edm.getPrice() + ", " + edm.getAmount() + "\n");
}
}
}
@Override
public void buildFooter(ExportFooterModel efm) {
buffer.append(efm.getExportUser());
}
public StringBuffer getResult() {
return buffer;
}
}
\export\XmlBuilder.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 实现导出数据到XML文件的具体生成器类
*/
public class XmlBuilder implements Builder {
/**
* 用来记录构建的文件的内容,相当于产品
*/
private StringBuffer buffer = new StringBuffer();
@Override
public void buildHeader(ExportHeaderModel ehm) {
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");
}
@Override
public void buildBody(Map<String, Collection<ExportDataModel>> mapData) {
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");
}
@Override
public void buildFooter(ExportFooterModel efm) {
buffer.append(" <Footer>\n");
buffer.append(" <ExportUser>" + efm.getExportUser() + "</ExportUser>\n");
buffer.append(" </Footer>\n");
buffer.append("</Report>\n");
}
public StringBuffer getResult() {
return buffer;
}
}
\export\Director.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export;
import java.util.Collection;
import java.util.Map;
/**
* 指导者,指导使用生成器的接口来构建输出的文件的对象
*/
public class Director {
/**
* 持有当前需要使用的生成器对象
*/
private Builder builder;
/**
* 构造方法,传入生成器对象
* @param builder 生成器对象
*/
public Director(Builder builder) {
this.builder = builder;
}
/**
* 指导生成器构建最终的输出文件的对象
* @param ehm 文件头的内容
* @param mapData 数据的内容
* @param efm 数据尾的内容
*/
public void construct(ExportHeaderModel ehm,
Map<String, Collection<ExportDataModel>> mapData,
ExportFooterModel efm) {
// 1: 先构建Header
builder.buildHeader(ehm);
// 2: 然后构建Body
builder.buildBody(mapData);
// 3: 再构建Footer
builder.buildFooter(efm);
}
}
\user\Client2.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package user;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import export.Director;
import export.ExportDataModel;
import export.ExportFooterModel;
import export.ExportHeaderModel;
import export.TxtBuilder;
import export.XmlBuilder;
public class Client2 {
public static void main(String[] args) {
// 准备测试数据
ExportHeaderModel ehm = new ExportHeaderModel();
ehm.setDepId("一分公司");
ehm.setExportDate("2013-06-02");
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(108);
edm2.setAmount(56);
// 把数据组装起来
col.add(edm1);
col.add(edm2);
mapData.put("销售记录表", col);
ExportFooterModel efm = new ExportFooterModel();
efm.setExportUser("李小二");
// 测试输出到文本文件
TxtBuilder txtBuilder = new TxtBuilder();
// 创建指导者对象
Director txtDirector = new Director(txtBuilder);
txtDirector.construct(ehm, mapData, efm);
// 把要输出的内容输出到控制台看看
System.out.println("输出到文本文件的内容: \n" +
txtBuilder.getResult());
// 测试输出到xml文件
XmlBuilder xmlBuilder = new XmlBuilder();
// 创建指导者对象
Director xmlDirector = new Director(xmlBuilder);
xmlDirector.construct(ehm, mapData, efm);
// 把要输出的内容输出到控制台看看
System.out.println("输出到XML文件的内容: \n" +
xmlBuilder.getResult());
}
}
@@@模式的实现:
1. 生成器中的每个方法可以有两部分的功能,一部分是创建部件对象,另一部分是组装部件。
2. 指导者承担的是整体构建算法部分,是相对不变的。
3. 产品构建过程中,指导者和生成器之间可能会存在比较复杂的交互过程。
4. 客户端最终从Builder实现里面获取最终装配好的产品。
5. 一般不需要对产品定义抽象接口,因为最终构建出来的产品千差万别。
@@@模式的功能:
生成器模式的主要功能是构建复杂的产品,而且是细化的、分步骤地构建产品,
也就是生成器模式重在一步一步解决构造复杂对象的问题。
更重要的是,这个构建的过程是统一的、固定不变的,变化的部分放到生成器部分了,只要配置不同的生成器,
那么同样的构建过程,就能构建出不同的产品来。
@@@模式的构成:
1. Builder接口,定义了如何构建各个部件,如何装配产品。
2. Director,定义了使用部件装配产品的步骤。
@@@模式的优点:
1. 松散耦合。
2. 可以很容易地改变产品的内部表示。
3. 更好的复用性
@@@模式的缺点:
无
@@@模式的本质:
分离整体构建算法和部件构造过程。
@@@模式体现的设计原则:
无