在建造大楼的时候,需要先打牢地基,搭建框架,再自下而上一层层盖,构建这类具有复杂结构的物体时,很难一气呵成。所以我们需要首先建造组成这个物体的各个部分,然后分阶段将它们组装起来。
首先需要一个Builder类,声明了方法的抽象类。
public abstract class Builder {public abstract void makeTitle(String title);public abstract void makeString(String title);public abstract void makeItems(String[] items);public abstract void close();}
其次需要一个Director来管理所有的类。
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();}}
其中的construct中使用是抽象方法。
Builder的实现类,将其中的抽象方法具体实现。 ```java public class TextBuilder extends Builder { private StringBuffer buffer = new StringBuffer();
@Override public void makeTitle(String title) {
buffer.append("===========================\n");buffer.append("["+title+"]");buffer.append("\n");
} @Override public void makeString(String str) {
buffer.append('O'+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();
}
} ``` 从代码中可以看出:Builder模型中有多个角色。
- Builder(建造者):
负责定义实例中的功能接口。
- ConCreteBuilder(具体的建造者):
负责实现Builder角色中的具体接口。
- Director(监工):
负责使用建造者的接口,不依赖于ConCreteBuilder,确保无论ConCreteBuilder是怎么定义的,Director都可以正常工作,只调用在Builder中定义的方法。
相关的设计模式:
Template Method:
在Builder模式中,Director角色控制Builder角色。在Template Method模式中,父类控制子类。
Composite模式:
有些情况下Builder模式生成的实例构成了Composite模式。
Abstract Factory模式:
Builder模式和Abstract Factory模式都用于生产复杂的实例。
Facade模式:
在Builder模式中,Director角色通过组合Builder角色中的复杂方法向外部提供可以简单生成实例的接口。
而Facade模式中的Facade角色则是通过组合内部模块向外部提供可以简单调用的接口。
思路:
可替换性:
Direct和Builder的子类并没有关联,Main类中调用的也是Direct而不是Builder,只有不知道子类才能替换。正是因为可以替换,组件才具有高价值。作为设计人员,“可替换性”非常重要。
设计接口时能够决定和不能决定的事情:
在Builder类中,需要声明实现功能所有需要的所有方法。Director类中使用的方法都是Builder中提供的。所以,在Builder中应当定义哪些方法是非常重要的。
而且,Builder类还必须能够应对将来子类可能增加的需求。在将来可能会对Builder建立新的子类,如果需要新的方法的话,之前的子类也要去实现其中的抽象方法。
所以,还是要尽可能让设计的类能够尽可能灵活地应对近期发生的变化。
问题:
如何在调用Builder的某些方法前,必须先调用一次makeTitle方法,且只能调用一次?
需要对Builder类中加入检查调用顺序的方法。使用新的方法来包装之前的接口,然后将之前的接口置为protected即可。
