定义
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
将复杂对象的创建过程与该对象的表示分离开来,以便让同一个创建过程可以创建出不同的表示。
类图
角色
- Builder:
定义一个抽象接口,用于创建Product组成部分 - ConcreteBuilder:
构建并组装Product组成部分;
定义并跟踪所创建的表示(Product?);
提供接口,用于查询product。 - Director:
使用Builder接口构建对象 - Product:
表示所创建的复杂对象;——ConcreteBuilder构建product的内部表示并定义它的组装过程;
包含定义组成部分的类。
示例代码
-
Product
public
class MyFile {
private FileHead fhead;
private FileContent fcontent;
private FileEnd fend;
public FileContent getFcontent() {
return fcontent;
}
public void setFcontent(FileContent fcontent) {
this.fcontent = fcontent;
}
public FileEnd getFend() {
return fend;
}
public void setFend(FileEnd fend) {
this.fend = fend;
}
public FileHead getFhead() {
return fhead;
}
public void setFhead(FileHead fhead) {
this.fhead = fhead;
}
public void write(String path) throws IOException{
File f=new File(path);
FileWriter fw=new FileWriter(f);
PrintWriter out=new PrintWriter(fw);
out.println(fhead.getValue());
out.println(fcontent.getValue());
out.println(fend.getValue());
out.close();
}
}
private FileHead fhead;
private FileContent fcontent;
private FileEnd fend;
public FileContent getFcontent() {
return fcontent;
}
public void setFcontent(FileContent fcontent) {
this.fcontent = fcontent;
}
public FileEnd getFend() {
return fend;
}
public void setFend(FileEnd fend) {
this.fend = fend;
}
public FileHead getFhead() {
return fhead;
}
public void setFhead(FileHead fhead) {
this.fhead = fhead;
}
public void write(String path) throws IOException{
File f=new File(path);
FileWriter fw=new FileWriter(f);
PrintWriter out=new PrintWriter(fw);
out.println(fhead.getValue());
out.println(fcontent.getValue());
out.println(fend.getValue());
out.close();
}
}
Product Part
public
class FileHead {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class FileContent{
private String value;
...
}
public class FileEnd {
private String value;
...
}
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class FileContent{
private String value;
...
}
public class FileEnd {
private String value;
...
}
-
Builder
public
interface FileBuilder {
void buildHead();
void buildContent();
void buildEnd();
MyFile getResult();
}
void buildHead();
void buildContent();
void buildEnd();
MyFile getResult();
}
-
ConcreteBuilder
public
class TxtBuilder
implements FileBuilder{
private FileHead fh=new FileHead();
private FileContent fc=new FileContent();;
private FileEnd fe=new FileEnd();
public void buildHead() {
fh.setValue("This is text file");
}
public void buildContent() {
fc.setValue("this is my content");
}
public void buildEnd() {
fe.setValue("this is the end of the file");
}
public MyFile getResult() {
MyFile my=new MyFile();
my.setFcontent(fc);
my.setFhead(fh);
my.setFend(fe);
return my;
}
}
private FileHead fh=new FileHead();
private FileContent fc=new FileContent();;
private FileEnd fe=new FileEnd();
public void buildHead() {
fh.setValue("This is text file");
}
public void buildContent() {
fc.setValue("this is my content");
}
public void buildEnd() {
fe.setValue("this is the end of the file");
}
public MyFile getResult() {
MyFile my=new MyFile();
my.setFcontent(fc);
my.setFhead(fh);
my.setFend(fe);
return my;
}
}
public
class XmlBuilder
implements FileBuilder {
private FileHead fh=new FileHead();
private FileContent fc=new FileContent();
private FileEnd fe=new FileEnd();
public void buildHead() {
fh.setValue("<?xml version=\"1.0\" encoding=\"GB2312\"?><content>");
}
public void buildContent() {
fc.setValue("<test>asdasd</test>");
}
public void buildEnd() {
fe.setValue("</content>");
}
private FileHead fh=new FileHead();
private FileContent fc=new FileContent();
private FileEnd fe=new FileEnd();
public void buildHead() {
fh.setValue("<?xml version=\"1.0\" encoding=\"GB2312\"?><content>");
}
public void buildContent() {
fc.setValue("<test>asdasd</test>");
}
public void buildEnd() {
fe.setValue("</content>");
}
//组装product
public MyFile getResult() {
MyFile my=new MyFile();
my.setFcontent(fc);
my.setFhead(fh);
my.setFend(fe);
return my;
}
}
public MyFile getResult() {
MyFile my=new MyFile();
my.setFcontent(fc);
my.setFhead(fh);
my.setFend(fe);
return my;
}
}
-
Director
public class FileDirector {
private FileBuilder filebuilder;
public FileDirector(FileBuilder filebuilder){
this.filebuilder=filebuilder;
}
//一步一步创建product
public void construct(){
filebuilder.buildHead();
filebuilder.buildContent();
filebuilder.buildEnd();
}
}
public void construct(){
filebuilder.buildHead();
filebuilder.buildContent();
filebuilder.buildEnd();
}
}
-
Client
public
class Demo {
public static void main(String[] args) throws IOException {
public static void main(String[] args) throws IOException {
//TxtBuilder
FileBuilder fb=new TxtBuilder();
FileDirector fd=new FileDirector(fb);
fd.construct();
MyFile my = fb.getResult();
my.write("D:/test.txt");
FileBuilder fb=new TxtBuilder();
FileDirector fd=new FileDirector(fb);
fd.construct();
MyFile my = fb.getResult();
my.write("D:/test.txt");
//XmlBuilder --改变builder,就改变了product的内部表示
FileBuilder fbxml=new XmlBuilder();
FileDirector fdxml=new FileDirector(fbxml);
fdxml.construct();
MyFile myxml=fbxml.getResult();
myxml.write("D:/test1.xml");
}
}
FileBuilder fbxml=new XmlBuilder();
FileDirector fdxml=new FileDirector(fbxml);
fdxml.construct();
MyFile myxml=fbxml.getResult();
myxml.write("D:/test1.xml");
}
}
优点
- 允许改变product的内部表示,定义一个新的builder即可。因为builder隐藏了product的表示和内部结构,也隐藏了product是如何组装的。
- 将构建和表示的代码分离开。将复杂对象的创建和表示封装起来,提供了模块化特性。每个ConcreteBuilder都定义了完整的创建和组装product的方法,不同的Director可以重用这些方法来构造不同的product。——也就是说可以替换Director,以便生成不同的product。
- 能更好地控制构建过程。并非一蹴而就地构建出product,而是在director的控制下一步一步地构建product。
缺点
适用场景
- 复杂对象的创建逻辑、其组成部分的创建逻辑、组装逻辑,互相独立。
- 构建过程允许对象有不同的表示。
诀窍
- AbstractBuilder中的方法留空,而不定义成抽象方法。
这样ConcreteBuilder就能按需实现方法,而不是实现所有方法。
- 为什么没有AbstractProduct?
一般ConcreteBuilder构建的product表示的差异很大。客户端会给director配置某个具体的ConcreteBuilder,所以客户端也就知道了会创建那种product。
- 为何不把builder中的逻辑移到Product中:
让Product尽可能小,易于理解和修改;
逻辑分开后,可以定义多种builder,实现不同的逻辑
Related Patterns
- Abstract Factory也是用来创建复杂对象,但是它着重于创建产品族;Builder则着重于一步一步地创建复杂对象。Builder是在最后一步返回product;而Abstract Factory立即返回product。
- Builder通常用来构建Composite。
作者:vking_wang 发表于2013-11-17 16:26:08 原文链接
阅读:46 评论:0 查看评论