构建者模式是什么?
简单来说,就是用于组装具有复杂结构的实例的模式。
什么意思呢?先来看个例子,比如现在有一个类TextBuilder用来创建一个文本内容,我们需要输入“大标题”、“小标题”、“内容”,用来构成这个文本内容。
public class TextBuilder {
private StringBuffer buffer = new StringBuffer();
// 先不看具体实现,只要知道需要依次调用一下方法,才能得到一个“文本内容”的实例
public void makeTitle(String title);
public void makeString(String str);
public void makeItems(String[] items);
public void close();
}
那么我们创建一个“文本内容”的实例就是这样的方式
import concrete_builder.TextBuilder;
public class Test {
public static void main(String[] args) {
TextBuilder textBuilder = new TextBuilder();
textBuilder.makeTitle("大标题");
textBuilder.makeString("小标题");
textBuilder.makeItems(new String[]{"内容1", "内容2"});
textBuilder.close();
// 好了,这时候的textBuilder才能正式使用
}
}
其实以上出现了这样几个角色:
- 使用者(Client)
- 监工(Director)
- 具体的建造者(TextBuilder)
使用者很好理解,就是我们(main方法)。而监工,意思就是监督建造者干活的人,在这里是不是感觉也由我们(使用者)充当了这个角色,因为都是我们手动去监督textBuilder调用那些“建造方法”。具体的建造者当然就是指TextBuilder了。
混在一起就比较复杂了,下面用构建者模式将各个角色的职责分开。
抽象建造者:只定义构建复杂对象的方法,具体实现由子类完成
public abstract class Builder {
public abstract void makeTitle(String title);
public abstract void makeString(String str);
public abstract void makeItems(String[] items);
public abstract void close();
}
监工:用于指导如何调用建造者的方法去 按顺序完成复杂对象的构建
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.makeTitle("Greeting");
builder.makeString("从早上至下午");
builder.makeItems(new String[]{"早上好。", "下午好。"});
builder.makeString("晚上");
builder.makeItems(new String[]{"晚上好", "晚安", "再见"});
builder.close();
}
}
具体的建造者:用什么样的结构来 组织监工传进来的内容。比如TextBuilder是用文本的形式,而HTMLBuilder是用Html的格式来构建。
public class TextBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();
@Override
public void makeTitle(String title) {
buffer.append("===============================\n");
buffer.append("【" + title + "】\n");
buffer.append("\n");
}
@Override
public void makeString(String str) {
buffer.append("str:" + str + "\n");
buffer.append("\n");
}
@Override
public void makeItems(String[] items) {
for (int i = 0; i < items.length; i++) {
buffer.append(" ." + items[i] + "\n");
}
buffer.append("\n");
}
@Override
public void close() {
buffer.append("===============================\n");
}
public String getResult() {
return buffer.toString();
}
}
public class HTMLBuilder extends Builder {
private String fileName;
private PrintWriter writer;
@Override
public void makeTitle(String title) {
fileName = title + ".html";
try {
writer = new PrintWriter(new FileWriter(fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
writer.println("<html><head><title>" + title + "</title></head><body>");
writer.println("<h1>" + title + "</h1>");
}
@Override
public void makeString(String str) {
writer.println("<p>" + str + "</p>");
}
@Override
public void makeItems(String[] items) {
writer.println("<ul>");
for (int i = 0; i < items.length; i++) {
writer.println("<li>" + items[i] + "</li>");
}
writer.println("</ul>");
}
@Override
public void close() {
writer.println("</body></html>");
writer.close();
}
public String getResult() {
return fileName;
}
}
使用者:只需要new好需要构建的复杂对象(这时候还是没内容的,是个空空如也的对象),然后丢给监工,监工指导一下构建者去完成复杂的组织过程,这时候我们再看这个复杂对象已经是组织好复杂内容的了。
public class Test {
public static void main(String[] args) {
TextBuilder textBuilder = new TextBuilder();
Director director = new Director(textBuilder);
director.construct();
String result = textBuilder.getResult();
System.out.println(result);
}
}
这样看是不是简洁了很多,再来一个需要构建html形式的对象也没问题,往监工里面一丢,监工指导一下,直接就拿到有内容,有结构的复杂Html对象了。
但是这里就是有个问题,会发现这些复杂对象的内容都是一样的(在监工指导的时候写死了),只是创建出结构不同的对象而已。如果要内容不一样的话,印象中需要将在监工中读取的内容抽成properties文件,然后改配置文件即可,不用去改监工的代码。
为什么要用构建者模式?
我的理解:应该是将职责分开吧,这样将复杂对象的构建过程就会更加清晰一点,也算是解耦了。并且将监工(Director)和抽象建造者(Builder)作为可复用的组件使用。