动机
格式转换器,将一种格式转换成多种格式
结构
参与者
Builder抽象类,多态调用:为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder:不同技艺的工人
- 实现Builder的接口以构造和装配该产品的各个部件
- 定义并明确它所创建的表示
- 提供一个检索产品的接口
Director:负责人
构建一个使用Builder接口的对象
Product
- 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
- 包含定义组成部件的类,包括将这些部件装配成最终产品的接口
工头来协调各个工人部件合作创建一所房子
伪代码如下:
public class FangZi {//产品
private String type;
private String amt;
get/set
}
public abstract class Builder{//生产者规范
public abstract void work();
public abstract void shouFei();
}
public class PingFangBuilder extend Builder{//生产者1
FangZi pingFang = new FangZi();
public void work() {//生产过程1
System.out.println("创建了平房");
pingFang.setType("平房");
}
public void shouFei(){//生产过程2
System.out.println("平房收费100");
pingFang.setType("100");
}
public FangZi getResult() {//产品输出
return FangZi;
}
}
public class BieShuBuilder extend Builder{//生产者2
FangZi pingFang = new FangZi();
public void work() {//生产过程1
System.out.println("创建了别墅");
pingFang.setType("平房");
}
public void shouFei(){//生产过程2
System.out.println("别墅收费1W");
pingFang.setType("1W");
}
public FangZi getResult() {//产品输出
return FangZi;
}
}
public class Director{//负责人
private Builder builder;
public Director(Builder builder) {//接收需求
this.builder = builder;
}
//调配工作
public void construct(){//感觉可以放在构造器中,但是太隐形了并且不符合逻辑顺序
builder.work();
builder.shouFei();
}
}
public class ClientUsr{//具体使用者
public static void main(String[] args) {
if(args[0] == 0) {
PingFangBuilder pingFangBu = new PingFangBuilder();
Director director = new Director(pingFangBu);
director.construct();
FangZi fangzi = pingFangBu.getResult();
}else {
BieShuBuilder pingFangBu = new BieShuBuilder();
Director director = new Director(pingFangBu);
director.construct();
FangZi fangzi = pingFangBu.getResult();
}
}
}
有疑问的地方:
- 为什么不在Director的构造器中实现construct()方法的功能,这样更便捷、更隐形;而且防止了客户端程序员忘记的可能风险
- 为什么不将getResult()放入Builder类中成为抽象方法,这样多态也可以产生,而且对于最后的客户端代码减少重复部分
协作
- 客户创建Director对象,并用它所想要的Builder对象进行配置
- 一旦产品部件被生成,导向器就会通知生成器
- 生成器处理导向器的请求,并将部件添加到该产品中
- 客户从生成器中检索产品
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时
优缺点
- 可以改变一个产品的内部表示;Builder对象提供给导向器一个构造产品的抽象接口。该接口使得生成器可以隐藏这个产品的表示和内部机构。它同时也隐藏了该产品时如何装配的。因为产品时通过抽象接口构造的,你在改变该产品的内部表示时所要做的只是定义一个新的生成器。
- 将构造代码和表示代码分开;Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息;这些类是不出现在Builder接口中的。每个ConcreteBuilder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同的Product
- 对构造过程进行更精细的控制 Builder模式与一下子就生成产品的创建型模式不同,他是在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回他。因为Builder接口相比其他创建型模式能更好的反映产品的构造过程。这使你可以更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。
实现
通常由一个抽象的Builder类为导向者可能要求创建的每一个构件定义一个操作。这些操作缺省情况下什么都不做。一个ConcreteBuilder类对它由兴趣创建的构件重定义这些操作
相关模式
Abstract Factory与Builder相似,因为它也可以创建复杂对象,主要区别是Builder模式着重于一步步构造一个复杂对象。而Abstract Factory着重于多个系列的产品对象(简单的或是复杂的)。Builder在最后的一步返回产品,而对于Abstract Factory来说,产品是立即返回的。
总结
区别
Abstract Factory就是去一家炒菜馆点菜,你可以点一个个的产品,点个西红柿炒鸡蛋
Builder是去美食城的盖浇饭点菜,你可以选一荤两素、两荤一素,一个个的选择部件,而不能让厨师直接制作
两种模式其实作用类似,可以实现的功能类似,区别是一个是多个产品,一个是一个产品的多个步骤