- 浏览: 458707 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (272)
- java基础 (59)
- struts (8)
- spring (8)
- 数据库 (8)
- java 网络编程 (29)
- hibernate (3)
- JavaScript (10)
- 日志管理 (2)
- jsp (4)
- servlet (7)
- xml (4)
- ajax (2)
- web service (4)
- 算法与数据结构 (13)
- java 反射机制 (11)
- java 泛型 (3)
- java I/O (8)
- java 线程 (12)
- JavaEE (6)
- java解惑 (33)
- 工具 (5)
- MyEclipse编程实践 (1)
- OSGI (2)
- 设计模式 (9)
- 正则表达式 (0)
- EJB (3)
- Ubuntu linux (6)
- Android (1)
- web前端 (2)
- 找工作 (1)
- SCA (1)
- maven (1)
- 缓存 (1)
- json (1)
- javamail (1)
- 工作笔记 (2)
最新评论
-
霜花似雪:
博主可以分享一下源码吗?
使用maven构建web项目实例 -
王庆波-行:
很好的demo!
memcache使用实例 -
surpassno:
大写的牛逼
java可视化显示内存使用情况 -
zhulin0504:
怎么访问NetEcho.html页面呀???
applet与servlet的网络通信 -
springdata:
java多线程实例demo源代码下载:http://www.z ...
java多线程例子
问题引人:继续导出数据的应用框架
讨论工厂方法模式时,提到了一个导出数据的应用框架。比如导出成文本格式,数据库备份形式,excel格式,xml格式等。
在工厂模式中,并没有讨论如何实现导出成文本、xml文件等,假如需求有以下:
1,导出的文件,不管什么格式,分为3部分,文件头,文件体和文件尾
2,在文件头,需要描述:分公司或门市点编号。导出数据的日期,对于文本格式,中间用逗号分隔。
3,文件体中,需要描述:表名称,然后分条描述数据。对于文本格式,表名称单独占一行,数据描述一行算一条数据,字段间用逗号分隔,
4,文件尾,需要描述:输出人
为简便起见,只实现导出成文本格式和Xml格式
要先将文件各个部分的数据对象定义出来。
上述实例notusingMode包中是没有使用模式的解决方案,观察程序可看出,无论导出为xml还是txt,步骤基本一样的,先拼接头,体,尾,最后将拼接完的
内容输出成为文件。也就是不同的输出格式,处理步骤是一样的,但是每一步的具体实现是不一样的,存在的问题如下:
(1)构建每种输出格式的文件内容时,都会重复这几个步骤,应该提炼出来,形成公共的处理过程。
(2)今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便地切换到不同的输出格式的处理。
构造每种格式的数据文件的处理过程,应该和具体的步骤实现分开,这样就能够复用处理过程,
而且能很容易切换到不同地输出格式。如何实现呢-----》生成器模式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以产生不同的表示。
思路:先把构建过程独立出来,在生成器模式中称为指导者,由他来指导装配过程,但是不负责每个步骤的具体实现,必须要有能具体实现每部的对象,
在生成器模式中,将这些对象称为生成器。这样,指导者就是可以重用的构建过程,但生成器就是可以被切换的具体实现。前面的每种具体的导出文件格式的实现
就相当于生成器。
生成器模式的结构:
(1)Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。
(2)ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时日工一个让用户获取组装完成后的产品对象的方法
(3)Director:指导者,主要用来使用Builder接口,以一个统一的过程来创建所需的Product对象
(4)Product:产品,表示被生成器构建的复杂对象,包含多个部件
两个重要部分:Builder接口,定义了如何构建各个部件,Director,是知道如何组合来构建产品,也就是说它负责整体的构建算法,通常是分步骤来执行。
生成器模式都存在两个部分,一个部分是部件构建和产品装配,另一个是整体构建的算法。它强调的是固定整体构建的算法,而灵活地扩展和切换部件的具体构造
生成器模式结构的实现代码:
使用生成器模式解决上述实际问题:
其中的模型部分(包括数据,头,尾)不用改变,需要增加的就是生成器对象等。
使用生成器模式构建复杂对象
实际应用,要创建一个保险合同的对象,里面有很多属性的值都有越是,比如合同可和个人签或是公司签,但不能同时和个人和公司签。如何创建呢?
由于用Builder模式创建某个对象,因此没有必要再定义一个Builder接口,直接提供一个具体的构建器类就可以了。还可以将指导者和客户端的功能合并起来。
例子:使用builder模式,先不考虑带约束,noRestrictContract包内.
使用builder模式,考虑带约束,restrictContract包内.
通常两个地方可以添加约束规则。(1)是构建器的每一个类似于setter的方法,可以在这里进行单个数据的约束规则校验,如果不正确,就抛出IllegalStateException
(2)构建器的build方法,在创建保险合同对象之前,对所有的数据都可以进行数据的约束规则校验,尤其是那些涉及到几个数据之间的约束关系,在这里校验会比较合适,如果不正确,就抛出IllegalStateException
更进一步,把构建器对象和被构建的对象合并
使用内联类,将构建器对象合并到被构建的对象里面去,如innerClassContract包中示例
builder模式的本质:分离整体构建算法和部件的构建
讨论工厂方法模式时,提到了一个导出数据的应用框架。比如导出成文本格式,数据库备份形式,excel格式,xml格式等。
在工厂模式中,并没有讨论如何实现导出成文本、xml文件等,假如需求有以下:
1,导出的文件,不管什么格式,分为3部分,文件头,文件体和文件尾
2,在文件头,需要描述:分公司或门市点编号。导出数据的日期,对于文本格式,中间用逗号分隔。
3,文件体中,需要描述:表名称,然后分条描述数据。对于文本格式,表名称单独占一行,数据描述一行算一条数据,字段间用逗号分隔,
4,文件尾,需要描述:输出人
为简便起见,只实现导出成文本格式和Xml格式
要先将文件各个部分的数据对象定义出来。
package notusingMode; //导出文件头模型对象 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; } }
package notusingMode; //描述导出数据的对象???? 即对应导出的文件体部分 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; } }
package notusingMode; //描述输出到文件尾的内容的对象 public class ExportFooterModel { private String exportUser; public String getExportUser() { return exportUser; } public void setExportUser(String exportUser) { this.exportUser = exportUser; } }
package notusingMode; //具体导出对象,导出到文件文件的对象 import java.util.Map; import java.util.Collection; public class ExportToTxt { // Map<String,Collection<ExportDataModel>>存储数据体,String类型的key代表表名称,后面的集合代表表格中的记录 public void export(ExportHeaderModel header,Map<String,Collection<ExportDataModel>> body,ExportFooterModel footer){ //用来记录最终输出的文件内容 StringBuffer buffer = new StringBuffer(); //1:先拼出文件头 buffer.append(header.getDepId()+","+header.getExportDate()+"\n"); //2:文件体 for(String tableName:body.keySet()){ //先拼接表格名称 buffer.append(tableName+"\n"); // 循环拼接具体数据 for(ExportDataModel data:body.get(tableName)){ buffer.append(data.getProductId()+","+data.getPrice()+","+data.getAmount()+"\n"); } } //3:文件尾 buffer.append(footer.getExportUser()+"\n"); //为了简单,不写出输出文件的代码了,将要输出的内容输出到控制台看看 System.out.println("输出到文本文件的内容是:\n"+buffer); } }
package notusingMode;
import java.util.Collection;
import java.util.Map;
public class ExportToXml {
// Map<String,Collection<ExportDataModel>>存储数据体,String类型的key代表表名称,后面的集合代表表格中的记录
public void export(ExportHeaderModel header,Map<String,Collection<ExportDataModel>> body,ExportFooterModel footer){
//用来记录最终输出的文件内容
StringBuffer buffer = new StringBuffer();
//1:先拼出文件头
buffer.append("<?xml version='1.0' encoding = 'gb2312' ?>\n");
buffer.append("<Report>\n");
buffer.append(" <Header>\n");
buffer.append(" <DeptId>"+header.getDepId()+"</DeptId>\n");
buffer.append(" <ExportDate>"+header.getExportDate()+"</ExportDate>\n");
buffer.append(" </Header>\n");
//2:文件体
buffer.append(" <Body>\n");
for(String tableName:body.keySet()){
//先拼接表格名称
buffer.append(" <Datas TableName=\""+tableName+"\">\n");
// 循环拼接具体数据
for(ExportDataModel data:body.get(tableName)){
buffer.append(" <Data>\n");
buffer.append(" <ProductID>"+data.getProductId()+"</ProductID>\n");
buffer.append(" <Price>"+data.getPrice()+"</Price>\n");
buffer.append(" <Amount>"+data.getAmount()+"</Amount>\n");
buffer.append(" </Data>\n");
}
buffer.append(" </Datas>\n");
}
buffer.append(" </Body>\n");
//文件尾
buffer.append(" <Footer>\n");
buffer.append(" <ExportUser>"+footer.getExportUser()+"</ExportUser>\n");
buffer.append(" </Footer>\n");
buffer.append("</Report>\n");
System.out.println("输出到XML文件的内容是:\n"+buffer);
}
}
上述实例notusingMode包中是没有使用模式的解决方案,观察程序可看出,无论导出为xml还是txt,步骤基本一样的,先拼接头,体,尾,最后将拼接完的
内容输出成为文件。也就是不同的输出格式,处理步骤是一样的,但是每一步的具体实现是不一样的,存在的问题如下:
(1)构建每种输出格式的文件内容时,都会重复这几个步骤,应该提炼出来,形成公共的处理过程。
(2)今后可能会有很多不同输出格式的要求,这就需要在处理过程不变的情况下,能方便地切换到不同的输出格式的处理。
构造每种格式的数据文件的处理过程,应该和具体的步骤实现分开,这样就能够复用处理过程,
而且能很容易切换到不同地输出格式。如何实现呢-----》生成器模式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以产生不同的表示。
思路:先把构建过程独立出来,在生成器模式中称为指导者,由他来指导装配过程,但是不负责每个步骤的具体实现,必须要有能具体实现每部的对象,
在生成器模式中,将这些对象称为生成器。这样,指导者就是可以重用的构建过程,但生成器就是可以被切换的具体实现。前面的每种具体的导出文件格式的实现
就相当于生成器。
生成器模式的结构:
(1)Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。
(2)ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时日工一个让用户获取组装完成后的产品对象的方法
(3)Director:指导者,主要用来使用Builder接口,以一个统一的过程来创建所需的Product对象
(4)Product:产品,表示被生成器构建的复杂对象,包含多个部件
两个重要部分:Builder接口,定义了如何构建各个部件,Director,是知道如何组合来构建产品,也就是说它负责整体的构建算法,通常是分步骤来执行。
生成器模式都存在两个部分,一个部分是部件构建和产品装配,另一个是整体构建的算法。它强调的是固定整体构建的算法,而灵活地扩展和切换部件的具体构造
生成器模式结构的实现代码:
package builder; //生成器接口 public interface Builder { //示意方法,构建某个部件,如果构建多个部件,就有多个方法 public void buildPart(); }
package builder; //具体生成器,负责实现各个部件的创建,并组装起来,提供给用户 public class ConcreteBuilder implements Builder { private Product resultProduct; @Override public void buildPart() { //构建某个部件的功能处理 } public Product getProduct(){ // 获取生成器最终构建的产品对象,返回给用户 return resultProduct; } }
package builder; //产品对象接口 public interface Product { }
package builder; //指导者,使用Builder接口来构建产品的对象 public class Director { private Builder builder; public Director(Builder builder) { //传入生成器对象 this.builder = builder; } public void construct(){ builder.buildPart(); // } }
使用生成器模式解决上述实际问题:
其中的模型部分(包括数据,头,尾)不用改变,需要增加的就是生成器对象等。
package builderSolve; import java.util.Collection; import java.util.Map; public interface Builder { public void buildHeader(ExportHeaderModel header); public void buildFooter(ExportFooterModel footer); public void buildBody(Map<String, Collection<ExportDataModel>> body); }
package builderSolve; import java.util.Collection; import java.util.Map; public class TxtBuilder implements Builder { private StringBuffer buffer = new StringBuffer(); public StringBuffer getResult(){ //返回构造完的复杂对象 return buffer; } @Override public void buildBody(Map<String,Collection<ExportDataModel>> body) { for(String tableName:body.keySet()){ //先拼接表格名称 buffer.append(tableName+"\n"); // 循环拼接具体数据 for(ExportDataModel data:body.get(tableName)){ buffer.append(data.getProductId()+","+data.getPrice()+","+data.getAmount()+"\n"); } } } @Override public void buildFooter(ExportFooterModel footer) { buffer.append(footer.getExportUser()+"\n"); } @Override public void buildHeader(ExportHeaderModel header) { buffer.append(header.getDepId()+","+header.getExportDate()+"\n"); } }
package builderSolve; import java.util.Collection; import java.util.Map; public class XmlBuilder implements Builder { private StringBuffer buffer = new StringBuffer(); public StringBuffer getResult() { // 返回构造完的复杂对象 return buffer; } @Override public void buildBody(Map<String, Collection<ExportDataModel>> body) { buffer.append(" <Body>\n"); for (String tableName : body.keySet()) { // 先拼接表格名称 buffer.append(" <Datas TableName=\"" + tableName + "\">\n"); // 循环拼接具体数据 for (ExportDataModel data : body.get(tableName)) { buffer.append(" <Data>\n"); buffer.append(" <ProductID>" + data.getProductId() + "</ProductID>\n"); buffer.append(" <Price>" + data.getPrice() + "</Price>\n"); buffer.append(" <Amount>" + data.getAmount() + "</Amount>\n"); buffer.append(" </Data>\n"); } buffer.append(" </Datas>\n"); } buffer.append(" </Body>\n"); } @Override public void buildFooter(ExportFooterModel footer) { //文件尾 buffer.append(" <Footer>\n"); buffer.append(" <ExportUser>"+footer.getExportUser()+"</ExportUser>\n"); buffer.append(" </Footer>\n"); buffer.append("</Report>\n"); } @Override public void buildHeader(ExportHeaderModel header) { buffer.append("<?xml version='1.0' encoding = 'gb2312' ?>\n"); buffer.append("<Report>\n"); buffer.append(" <Header>\n"); buffer.append(" <DeptId>" + header.getDepId() + "</DeptId>\n"); buffer.append(" <ExportDate>" + header.getExportDate() + "</ExportDate>\n"); buffer.append(" </Header>\n"); } }
package builderSolve; import java.util.Collection; import java.util.Map; //指导者,使用Builder接口来构建产品的对象 public class Director { private Builder builder; public Director(Builder builder) { //传入生成器对象 this.builder = builder; } public void construct(ExportHeaderModel header,Map<String,Collection<ExportDataModel>> body,ExportFooterModel footer){ builder.buildHeader(header); builder.buildBody(body); builder.buildFooter(footer); } }
package builderSolve; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class Client { public static void main(String[] args) { //准备测试数据 ExportHeaderModel header = new ExportHeaderModel(); header.setDepId("一分公司"); header.setExportDate("2011-03-25"); Map<String,Collection<ExportDataModel>> map = new HashMap<String,Collection<ExportDataModel>>(); Collection<ExportDataModel> collection = new ArrayList<ExportDataModel>(); ExportDataModel data1 = new ExportDataModel(); data1.setAmount(43); data1.setPrice(56.4); data1.setProductId("产品001号"); ExportDataModel data2 = new ExportDataModel(); data2.setAmount(444); data2.setPrice(26.4); data2.setProductId("产品002号"); collection.add(data2); collection.add(data1); map.put("销售记录表", collection); ExportFooterModel footer = new ExportFooterModel(); footer.setExportUser("张三"); // 测试输出到文本文件 TxtBuilder txtBuilder = new TxtBuilder(); Director director = new Director(txtBuilder); director.construct(header, map, footer); System.out.println("输出到txt文件的内容是:\n"+txtBuilder.getResult()); //测试输出到xml文件 XmlBuilder xmlBuilder = new XmlBuilder(); Director director2 = new Director(xmlBuilder); director2.construct(header, map, footer); System.out.println("输出到XML文件的内容是:\n"+xmlBuilder.getResult()); } }
使用生成器模式构建复杂对象
实际应用,要创建一个保险合同的对象,里面有很多属性的值都有越是,比如合同可和个人签或是公司签,但不能同时和个人和公司签。如何创建呢?
由于用Builder模式创建某个对象,因此没有必要再定义一个Builder接口,直接提供一个具体的构建器类就可以了。还可以将指导者和客户端的功能合并起来。
例子:使用builder模式,先不考虑带约束,noRestrictContract包内.
使用builder模式,考虑带约束,restrictContract包内.
通常两个地方可以添加约束规则。(1)是构建器的每一个类似于setter的方法,可以在这里进行单个数据的约束规则校验,如果不正确,就抛出IllegalStateException
(2)构建器的build方法,在创建保险合同对象之前,对所有的数据都可以进行数据的约束规则校验,尤其是那些涉及到几个数据之间的约束关系,在这里校验会比较合适,如果不正确,就抛出IllegalStateException
更进一步,把构建器对象和被构建的对象合并
使用内联类,将构建器对象合并到被构建的对象里面去,如innerClassContract包中示例
builder模式的本质:分离整体构建算法和部件的构建
- builder.rar (38.4 KB)
- 下载次数: 1
发表评论
-
中介者模式(mediator)
2011-05-06 15:37 809电脑的各个配件之间的 ... -
享元模式flyweight
2011-05-06 15:08 896问题引人:给系统加入权限控制,如普通人员可以查看本部门人员列表 ... -
责任链设计模式chainOfResponsibility
2011-05-06 14:50 978问题引人:申请聚餐费用,申请人填写申请单,然后交给领导审阅,如 ... -
外观模式facade
2011-05-06 14:24 903生活中的示例:组装电 ... -
观察者模式observer
2011-05-06 14:03 966问题引人:订阅报纸的过程: 订阅者---》邮局-----》报社 ... -
适配器模式adapter,含源码下载
2011-05-06 12:49 910引出:组装电脑例子,向电脑加入新硬盘,但电源和新的硬盘的电源接 ... -
抽象工厂模式abstractFactory
2011-05-06 12:38 977具体的实现代码见附件 ... -
原型设计模式prototype
2011-05-06 11:30 1306基于《研磨设计模式》,没什么实质突破,简单的记录一下 问题引人 ...
相关推荐
C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) 体验课程
文章地址:https://blog.csdn.net/mazhiyuan1981/article/details/110638833
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第4节:创建型模式Builder生成器模式
Builder(生成器)模式[文].pdf
【设计模式】- 生成器模式(Builder)(csdn)————程序
在《Head First Design Patterns》文中是这么介绍生成器模式的,“封装一个产品的构造过程,并允许按步骤构造”,感觉说得不是很清楚。而在网上查找相关资料是这么解释的,建造者模式(Builder Pattern)使用多个简单...
java设计模式之生成器模式,希望对大家有所帮助。
C#面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式) (Level 300)
C#视频-面向对象设计模式纵横谈(4):Builder 生成器模式(创建型模式)
Builder(生成器)模式借鉴.pdf
Builder(生成器)模式参照.pdf
Builder(生成器)模式定义.pdf
宏海科技代码生成器(1.0 bete) 使用说明: 采用三层模式生成代码 ,每个层都分为两部分 Auto文件夹为自动生成的完整代码,外面的为用户自己写方法用。 1: 先将三层搭建好(实在懒的话,一个项目也行),添加好引用,...
FreeBuilder为 Java 1.6 自动生成 Builder 模式。当设计类的构造函数或静态工厂具有多个参数时,Builder 模式是一个不错的选择。—— Effective Java,第二版,第39页背景在 Java 中实现 Builder 模式容易出错和...
主要介绍了C#设计模式之Builder生成器模式解决带老婆配置电脑问题,简单介绍了生成器模式的概念、功能并结合具体实例形式分析了C#生成器模式解决配电脑问题的步骤与相关操作技巧,需要的朋友可以参考下
myeclipse插件配置代码生成器和指导
该项目演示了如何使用.NET 5 Source生成器来自动生成类的生成器模式。 有关此项目的完整详细信息,。 请注意,这是有效的POC样本,而不是生产等级代码。它有什么作用变成这个[ GenerateBuilder ]public partial ...
自动为Java 1.8+生成Builder模式 当设计类的构造函数或静态工厂将具有多个参数的类时,Builder模式是一个不错的选择。 —有效的Java,第二版,第39页 背景 在Java中实现非常繁琐,容易出错且重复。 谁没有看过一个...