将一个复杂对象的构件与它的表示分离,是的同样的构建可以创建不同的表示。
对象性质的建造
- 有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用。
- 有些情况下,一个对象的一些性质必须按照某个顺序复制才有意义。在某个性质没有赋值之前,另一个性质则无法赋值。这些情况是的性质本身的建造涉及到复杂的商业逻辑。
这时候,此对象相当于一个有待建造的产品,而对象的这些性质相当于产品的零件,建造产品的过程就是组合零件的过程。由于组合零件的过程很复杂,因此,这些“零件”的组合过程往往被“外部化”到一个称作建造者的对象里,建造者返还给客户端的是一个全部零件都建造完毕的产品对象。
思路
- 先把构建过程独立出来,在建造者模式中把它称为指导者,由他来知道装配过程。但不负责每步具体的实现。
- 要有能具体实现每步的对象,称之为建造者或者生成器。
建造者模式的结构
- 建造者(Builder)角色
定义创建一个Product对象所需的各个部件的操作。 - 具体建造者(Concrete Builder)角色
实现Builder角色提供的接口,一步一步完成穿件产品实例的过程。
在建造过程完后才能后,提供产品的实例。 - 指导者(Director)角色
主要用来使用Builder接口,以一个统一的过程来构件所需要的Product对象。 - 产品(Product)角色
产品便是建造中的复杂对象。
客户端作用
客户端负责创建指导者和具体建造者对象。然后,客户端把具体建造者对象交给指导者。客户一声令下,指导者操纵建造者开始创建产品。当产品创建完成后,建造者把产品返还给客户端。
在什么情况下使用建造者模式
- 需要生成的产品对象有复杂的内部结构。
- 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
- 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到。
优点
- 建造者模式的使用是的产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 每一个Builder都相对立,而与其他的Builder无关。
- 模式所建造的最终产品更易于控制。
本质
分离整体构建算法和部件构造。
实例
【问题】
继续工厂方法章节的补充例子,用建造者模式实现(代码+UML图) :
(1) 导出数据的应用框架,通常对于具体的导出内容和格式是有要求的:分成三部分,文件头、文件体、文件尾
文件头:分公司编号、导出数据的日期,对于文本格式,中间用逗号分离
文件体:表名称,然后分条描述数据。
文件尾:输出人
(2)不管是输出文本文件,还是输出XML文件,步骤基本一致
先拼接文件头的内容
然后拼接文件体的内容
在拼接文件尾的内容
最后把拼接好的内容输出去成为文件
【代码】
ps:理解有些问题,代码可能有问题。
public abstract class FileExport {
public abstract void WriteHead(String num);
public abstract void WriteMain(String name,String data);
public abstract void WriteTail(String person);
}
public class XMLExport extends FileExport {
@Override
public void WriteHead(String num) {
Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String createdate = sdf.format(date);
String overall="表编号:"+num+",建表日期:"+createdate;
System.out.println("输出到XML头部:"+overall);
}
@Override
public void WriteMain(String name, String data) {
String overall="表名:"+name+",表中数据:"+data;
System.out.println("输出到XML主体:"+overall);
}
@Override
public void WriteTail(String person) {
String overall="输出人:"+person;
System.out.println("输出到XML尾部:"+overall);
}
}
public class TxtExport extends FileExport {
String filePath =null;
File file=null;
BufferedWriter br = null;
FileWriter fr = null;
public TxtExport() {}
public TxtExport(String filePath, File file, BufferedWriter br,
FileWriter fr) {
super();
this.filePath = filePath;
this.file = file;
this.br = br;
this.fr = fr;
}
@Override
public void WriteHead(String num) {
Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String createdate = sdf.format(date);
String overall="表编号:"+num+",建表日期:"+createdate;
try {
fr = new FileWriter(file, true);
br = new BufferedWriter(fr);
br.newLine();
br.write(overall);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void WriteMain(String name,String data) {
String overall="表名:"+name+",表中数据:"+data;
try {
fr = new FileWriter(file, true);
br = new BufferedWriter(fr);
br.newLine();
br.write(overall);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void WriteTail(String person) {
String overall="输出人:"+person;
try {
fr = new FileWriter(file, true);
br = new BufferedWriter(fr);
br.newLine();
br.write(overall);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Director {
FileExport fep;
public Director(FileExport fep) {
super();
this.fep = fep;
}
public Director() {}
public void Export(String num,String name,String data,String person)
{
fep.WriteHead(num);
fep.WriteMain(name, data);
fep.WriteTail(person);
}
}
public class Cliect {
public static void main(String[] args) {
String filePath = "D:\\APPS\\JAVA WORKPLACE\\SJMS_08\\src\\Builder\\test.txt";
File file = new File(filePath);
BufferedWriter br = null;
FileWriter fr = null;
FileExport tep=new TxtExport(filePath,file,br,fr);
FileExport xep=new XMLExport();
Director d1=new Director(tep);
d1.Export("1", "设计模式", "数据1", "小菜");
Director d2=new Director(xep);
d2.Export("2", "设计模式", "数据2", "大鸟");
}
}
【UML图】