建造者模式(Builder)
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
动机
建造者返回给客户一个完整的的产品对象,而客户端无须关心该对象所包含的属性和组建方式。
如果想要通俗易懂可以参考《大话设计模式》第13章建造模式部分,里面通过做饭来引出建造者模式,用户去吃饭,无需知道师傅放的什么食材以及如何烹饪。再者,还拿汽车来说,我们去买汽车无需知道汽车具体的零件和如何组装的。
假如我们要生产一辆车,假如我们只考虑车有四个轮子,一个发动机,一个车架,常规方法我们需要再需要车的地方,生产四个轮子,一个车架,一个发动机,当我们对车的轮子或者发动机有新的需求,我们又要重改代码,假如我们再另一个地方又需要创建一台车,那么又需要把代码重写一遍,构建过程无法被复用,代码凌乱, 容易错写或者少写,假如少生产一个轮子,那么这个对象就没有使用价值了。
建造者模式就适合解决这一类问题:构建一个对象的过程是相同的,只不过是细节是不同的。也就实现了建造者模式的初衷:构建和表示分离,使得同样的构建过程可以创建不同的表示。
使用场景
(1) 需要生成的产品对象有复杂的内部结构。
(2) 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
(3) 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
(4) 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
结构
角色
Builder
为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder
1.实现Builder以构造和装配该产品的各个部件。
2.定义并明确它所创建的表示。
3.提供一个检索产品的接口。
Director
指导构造一个使用Builder接口的对象
Product
被构造的复杂对象。
协作
效果
- 可以改变一个产品的内部表示。
- 将构造和表示分离。
- 对构建的过程进行更加精细的控制。
相关模式
- Abstract Factory(3.1)与Builder相似,因为它也可以创建复杂对象。主要的区别是Builder模式着重于一步步构造一个复杂对象(主要是体现构造同一个产品的过程),Abstract Factory着重于多个系列的产品对象(简单的或是复杂的产品族中的不同产品)。Builder在最后的一步返回产品,而对于Abstract Factory来说,产品是立即返回的。
- Composite(4.3)通常是用Builder生成的。
具体场景代码描述
/**
* 场景:简单一点的例子,我们制造一辆自行车,主要构成包括:前轮子,后轮子,车架,链子
* 第一步:创建一个Builder抽象类,来将制造过程给稳定(非制造顺序,而是包括哪些步骤),这样就可以避免我们在常规制造中漏步骤的问题(比如少了链子)
* 第二步:创建一个具体的建造者去继承这个方法,去建造一个具体的对象,具体的构造方式写在此类中。
* 第三步:创建一个Director,去指导制造过程(可以在此改变制造的顺序)。
* 第四步:写客户端代码进行测试
*/
//第一步:创建一个Builder抽象类,规定了这些步骤,具体对象去继承就不会遗漏制造过程。
public abstract class Builder {
/**
* builder前轮
*/
public abstract void BuilderFrontWheel();
/**
* builder后轮
*/
public abstract void BuilderBackWheel();
/**
* 构建框架
*/
public abstract void BuilderFrame();
/**
* 构建链子
*/
public abstract void BuilderChain();
}
//第二步:创建一个具体的建造者ConcreteBuilderA去建造一个大车架的自行车,ConcreteBuilderB去建造一个小车架的自行车。
public class ConcreteBuilderA extends Builder{
/**
* builder前轮
*/
@Override
public void BuilderFrontWheel() {
System.out.println("制造前轮");
}
/**
* builder后轮
*/
@Override
public void BuilderBackWheel() {
System.out.println("制造后轮");
}
/**
* 构建框架
*/
@Override
public void BuilderFrame() {
System.out.println("制造大车架");
}
/**
* 构建链子
*/
@Override
public void BuilderChain() {
System.out.println("制造链子");
}
}
public class ConcreteBuilderB extends Builder{
/**
* builder前轮
*/
@Override
public void BuilderFrontWheel() {
System.out.println("制造前轮");
}
/**
* builder后轮
*/
@Override
public void BuilderBackWheel() {
System.out.println("制造后轮");
}
/**
* 构建框架
*/
@Override
public void BuilderFrame() {
System.out.println("制造小车架");
}
/**
* 构建链子
*/
@Override
public void BuilderChain() {
System.out.println("制造链子");
}
}
//第三步:创建一个指导者(Director)
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void createBicycle(){
builder.BuilderBackWheel();
builder.BuilderFrontWheel();
builder.BuilderFrame();
builder.BuilderChain();
}
}
//创建客户端代码测试
public class Client {
public static void main(String[] args) {
System.out.println("--------------------制造大轮子车--------------------------");
new Director(new ConcreteBuilderA()).createBicycle();
System.out.println("--------------------制造小轮子车--------------------------");
new Director(new ConcreteBuilderB()).createBicycle();
}
}
//结果
--------------------制造大轮子车--------------------------
制造后轮
制造前轮
制造大车架
制造链子
--------------------制造小轮子车--------------------------
制造后轮
制造前轮
制造小车架
制造链子
以上案例只说明了建造者模式的使用,未创建出具体的自行车类,如果需要封装也很简单,具体代码改变如下:
//Bicycle
public class Bicycle {
private String frontWheel;
private String backWheel;
private String frame;
private String chain;
public void setFrontWheel(String frontWheel) {
this.frontWheel = frontWheel;
}
public void setBackWheel(String backWheel) {
this.backWheel = backWheel;
}
public void setChain(String chain) {
this.chain = chain;
}
public void setFrame(String frame) {
this.frame = frame;
}
@Override
public String toString() {
return "Bicycle{" +
"frontWheel='" + frontWheel + '\'' +
", backWheel='" + backWheel + '\'' +
", frame='" + frame + '\'' +
", chain='" + chain + '\'' +
'}';
}
}
//Builder
public abstract class Builder {
protected Bicycle bicycle = new Bicycle();
/**
* builder前轮
*/
public abstract void builderFrontWheel();
/**
* builder后轮
*/
public abstract void builderBackWheel();
/**
* 构建框架
*/
public abstract void builderFrame();
/**
* 构建链子
*/
public abstract void builderChain();
public Bicycle getBicycle(){
return bicycle;
}
}
//ConcreteBuilderA|B
public class ConcreteBuilderA extends Builder {
/**
* builder前轮
*
*/
@Override
public void builderFrontWheel() {
bicycle.setFrontWheel("前轮");
}
/**
* builder后轮
*
*/
@Override
public void builderBackWheel() {
bicycle.setBackWheel("后轮");
}
/**
* 构建框架
*/
@Override
public void builderFrame() {
bicycle.setFrame("大车架");
}
/**
* 构建链子
*
*/
@Override
public void builderChain() {
bicycle.setChain("链子");
}
}
public class ConcreteBuilderB extends Builder {
/**
* builder前轮
*
*/
@Override
public void builderFrontWheel() {
bicycle.setFrontWheel("前轮");
}
/**
* builder后轮
*
*/
@Override
public void builderBackWheel() {
bicycle.setBackWheel("后轮");
}
/**
* 构建框架
*/
@Override
public void builderFrame() {
bicycle.setFrame("小车架");
}
/**
* 构建链子
*
*/
@Override
public void builderChain() {
bicycle.setChain("链子");
}
}
//Director
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Bicycle buildeBicycle(){
builder.builderFrontWheel();
builder.builderBackWheel();
builder.builderFrame();
builder.builderChain();
return builder.getBicycle();
}
}
//Client
public class Client {
public static void main(String[] args) {
System.out.println("--------------------制造大轮子车--------------------------");
Bicycle bicycleA = new Director(new ConcreteBuilderA()).buildeBicycle();
System.out.println(bicycleA.toString());
System.out.println("--------------------制造小轮子车--------------------------");
Bicycle bicycleB = new Director(new ConcreteBuilderB()).buildeBicycle();
System.out.println(bicycleB.toString());
}
}
//结果
--------------------制造大轮子车--------------------------
Bicycle{frontWheel='前轮', backWheel='后轮', frame='大车架', chain='链子'}
--------------------制造小轮子车--------------------------
Bicycle{frontWheel='前轮', backWheel='后轮', frame='小车架', chain='链子'}
Note:如有错误,欢迎指正。