参考

1. Builder Design Pattern | Youtube

2. 建造者模式(Builder和Director)| 博客园

3. 深入理解Builder模式 | 简书

建造者模式(Builder Pattern)

将一个复杂对象的构建与表示分离,使得同样的构建过程可以不同的表示。

通常,在建造者Builder中包含多个不同的属性(基本类型或者别的类对象),这些属性由Builder的方法构建,由Director来组装出一种产品Product。 也就是说,Builder Pattern的目的是为了构建一个或多个Product,不同的构建过程可以表示不同Product。每一个Builder至少代表了一种不同属性的组合,以组装成产品。

组成

Builder 为创建一个Product对象的各个部件指定的抽象接口
ConcreteBuilder 

实现Builder接口,构造和装配Product产品的各个部件;

定义并明确所创建的表示;

提供一个获取Product的接口。

Director 构造一个使用Builder接口对象
Product

被构造的复杂对象;

由ConcreteBuilder内部表示和定义它的装配过程;

包含了组成部件/属性的类,包括将这些部件装配成最终产品的接口。

适用场景

[参考1~2]:建造者模式用于创建的Product对象,由其他多个对象组成。

1)当你想建造的对象由其他对象(称为部件)组成;

2)当你想这些组件的创建独立于主要对象;

3)隐藏来自client的部分的创建,以至于这部分和创建对象是相互独立的;

4)建造者知道细节,并且别人不知道;

通俗讲,当自己想创建的对象由多个其他类对象组成,并且希望自己创建的对象独立于其他对象的创建,用户不必知道创建这个对象的细节,只需要指定特定Builder来负责建造组件、Director负责何时组装以及如何组装即可。

特点

1) 分步构建一个复杂对象。Product通常由别的多个不同的子对象组成,builder提供构建接口和获取最终产品对象的接口。

2) 支持多种构建表示。Builder模式封装了构建的过程,用户只需传入关心的参数和必须的参数,而不用关心复杂的构建过程,就能创建出不同的表示。

3) 将部件的创建和部件的组装方式解耦,部件类型和部件装配方式互不影响。

缺点

1) 不适合包含同类别子对象的Product创建,如组合模式;

2) 当Product增加部件时,可能会导致Builder及其子类, Director的大量修改;

与工厂模式,抽象工厂比较

工厂模式:提供统一的抽象接口,让子类决定实例化哪一个类,使对象的初始化延迟到子类进行。

抽象工厂:为创建一组相关或者相互依赖的对象提供一个接口,而无需指定他们具体的类。

1. 建造者 vs 工厂模式

工厂模式通常只生产一种产品,而且产品之间没有必然联系。侧重于表示接口和Product之间的关系。

建造者模式可以产生一种或多种产品表示,不同的构建过程可以表示不同Product。侧重于用多个部件构建复杂产品表示的过程。

2. 建造者 vs 抽象工厂

抽象工厂往往产出多个Product,并且Product之间存在一定关联或依赖关系。每个具体Product要求用工厂来创建。抽象工厂的具体工厂生产产品,可以用Builder模式来创建。侧重于表示一组方案。

建造者模式通常产生1个产品,不同的构建过程有不同的Product表示。侧重于表示1个复杂产品的构建的过程。

通用类图

 Figure1 Builder Pattern通用类图

demo

下面这个例程跟网上流传的“造人”"造船"例程很像,能体现Builder模式的基本特点,“将对象的创建与表示分离”。但是有一个缺点,就是一个Builder只能生产一种产品对象,因为产品组件在Builder中的创建已经固化了,当需要添加一种对象时,就需要添加一种Builder。

[参考1] Client要创建Robot,就需要通过RobotBuilder创建OldStyleRobotBuilder,然后再创建RobotEngineer(Robot工程师),在RobotEngineer通过RobotPlan(Robot设计)创建Robot对象。创建过程如Figure2.

Figure2 Client创建Robot过程

 

Figure3 demo的UML类图

代码

1. 创建Robot接口RobotPlan,定义各属性设置的公共方法

RoboPlan.java

public interface RobotPlan {

    public void setHead(String head);

    public void setTorso(String torso);

    public void setArms(String arms);

    public void setLegs(String legs);
}

2.定义Robot,实现RobotPlan接口,这里的几个属性用String类型

Robot.java

public class Robot implements RobotPlan {
private String head;
private String torso;
private String arms;
private String legs; @Override
public void setHead(String head) { this.head = head; } public String getHead() { return head; } @Override
public void setTorso(String torso) { this.torso = torso; } public String getTorso() { return torso; } @Override
public void setArms(String arms) { this.arms = arms; } public String getArms() { return arms; } @Override
public void setLegs(String legs) { this.legs = legs; } public String getLegs() { return legs; }
}

3.定义Robot的Builder 接口RobotBuilder,声明构建Robot子对象/属性的公共方法,读取Robot的方法

RobotBuilder.java

public interface RobotBuilder {

    public void buildHead();

    public void buildTorso();

    public void buildArms();

    public void buildLegs();

    public Robot getRobot();
}

4.定义OldStyleRobotBuilder,实现接口RobotBuilder,负责具体构建Robot的子对象/属性

OldStyleRobotBuilder.java

/* 将robot各子部件固化到builder中 */
public class OldStyleRobotBuilder implements RobotBuilder { private Robot robot; public OldStyleRobotBuilder(){
robot = new Robot();
} @Override
public void buildHead() {
robot.setHead("Tin Head");
} @Override
public void buildTorso() {
robot.setTorso("Tin Torso");
} @Override
public void buildArms() {
robot.setArms("Blowtorch Arms");
} @Override
public void buildLegs() {
robot.setLegs("Roller Legs");
} @Override
public Robot getRobot() {
return robot;
} }

5. 定义Director RobotEngineer,指导RobotBuilder构建Robot

RobotEngineer.java

/* 指导RobotBuilder构建Robot*/
public class RobotEngineer {
private RobotBuilder robotBuilder; public RobotEngineer (RobotBuilder robotBuilder){
this.robotBuilder = robotBuilder;
} public void makeRobot(){
robotBuilder.buildHead();
robotBuilder.buildTorso();
robotBuilder.buildArms();
robotBuilder.buildLegs(); // 另外一种方式是在此处创建Robot, 然后将build构建的结果复制给Robot
} public Robot getRobot(){
return robotBuilder.getRobot();
}
}

6. RobotBuilderDemo(Client)测试例程

1) 第一步是创建RobotBuilder具体对象

2) 第二步是创建Director RobotEngineer,用于指导构建Robot

3) 第三步是制造/组装Robot

4) 第四步是测试组装的Robot属性

public class RobotBuilderDemo {

    public static void main(String[] args){
RobotBuilder robotBuilder = new OldStyleRobotBuilder();
RobotEngineer robotEngineer = new RobotEngineer(robotBuilder);
robotEngineer.makeRobot(); Robot robot = robotEngineer.getRobot();
System.out.println("Robot build component:");
System.out.println("Robot Head: "+robot.getHead());
System.out.println("Robot Torso: "+robot.getTorso());
System.out.println("Robot Arms:"+robot.getArms());
System.out.println("Robot Legs:"+robot.getLegs());
}
}

7. 运行结果

总结

1. 产品的参数往往由外部Client来决定,因此可以将Builder中构建Product属性的方法设为由外部参数决定。

例如,public void buildHead(); 可修改为public void buildHead(String head)

设计模式01 创建型模式 - 建造者模式(Build Pattern)的更多相关文章

  1. 设计模式01 创建型模式 - 单例模式(Singleton Pattern)

    参考 [1] 设计模式之:创建型设计模式(6种) | 博客园 [2] 单例模式的八种写法比较 | 博客园 单例模式(Singleton  Pattern) 确保一个类有且仅有一个实例,并且为客户提供一 ...

  2. 设计模式01 创建型模式 - 原型模式(Protype Pattern)

    参考 1. 设计模式:原型模式 | 博客园 2. Java clone深拷贝.浅拷贝 | CSDN 3. Cloneable接口和Object的clone()方法 | 博客园 原型模式(Prototy ...

  3. 设计模式学习-使用go实现建造者模式

    建造者模式 定义 适用范围 与工厂模式的区别 优点 缺点 参考 建造者模式 定义 Builder 模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式. 建造者模式(Builder Patt ...

  4. js常用设计模式实现(三)建造者模式

    创建型模式 创建型模式是对一个类的实例化过程进行了抽象,把对象的创建和对象的使用进行了分离 关于创建型模式,已经接近尾声了,还剩下建造者模式和原型模式,这一篇说一说建造者模式 建造者模式的定义 将一个 ...

  5. java设计模式(二)单例模式 建造者模式

    (三)单例模式 单例模式应该是最常见的设计模式,作用是保证在JVM中,该对象仅仅有一个实例存在. 长处:1.降低某些创建比較频繁的或者比較大型的对象的系统开销. 2.省去了new操作符,减少系统内存使 ...

  6. 设计模式之第11章-建造者模式(Java实现)

    设计模式之第11章-建造者模式(Java实现) “那个餐厅我也是醉了...”“怎么了?”“上菜顺序啊,竟然先上甜品,然后是冷饮,再然后才是菜什么的,无语死了.”“这个顺序也有人这么点的啊.不过很少就是 ...

  7. Java设计模式(四)Builder建造者模式

    一.场景描述 建造者模式同工厂模式.抽象工厂模式一样,用于创建继承类对象. 工厂模式:http://www.cnblogs.com/mahongbiao/p/8618970.html 抽象工厂模式:h ...

  8. (转自精通Python设计模式)Python设计模式之创建型模式——2.建造者模式

    建造者模式将一个复杂对象的构造过程与其表现分离,这样,同一个构造过程可用于创建多个不同的表现. 我们来看个实际的例子,假设我们想要创建一个HMTL页面生成器,HTML页面的基本结构(构造组件)通常是一 ...

  9. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

随机推荐

  1. win7 安装asp.net v4.0

    错误信息影响: HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容.返回的错误表明IIS缺少针对无后缀的MVC请求的映射,ASP.NET处理程序无法接收到请 ...

  2. office2013激活工具,可以激活新版本office 2013

    耽误一上午没激活成功,最后还是找到了激活文件KMSpico v9.0.6.zip 链接:https://pan.baidu.com/s/1WEyJm8kVnqDONRJRHTRQiQ 提取码:4h45 ...

  3. Loppinha, the boy who likes sopinha Gym - 101875E (dp,记忆化搜索)

    https://vjudge.net/contest/299302#problem/E 题意:给出一个01 0101串,然后能量计算是连续的1就按1, 2, 3的能量加起来.然后给出起始的能量,求最少 ...

  4. Python学习(七)——匿名函数、map函数、filter函数、reduce函数与其他内置函数

    匿名函数 lambda x: x + 1 # lambda:定义匿名函数的关键字 # x:形参 # x+1:程序处理逻辑 fun = lambda x: x + 1 print(fun(5)) #6 ...

  5. 【npm】安装、搭建独立项目环境

    目录 安装npm包的几种方式 搭建独立的项目环境 npm常用命令 package.json文件详述 "任何一门计算机语言都包含了丰富的第三方库,npm就是JavaScript这门语言的第三方 ...

  6. 使用jenkins 实现 .net core项目自动发布到 docker

    在Docker内运行Jenkins pull镜像  docker pull jenkins/jenkins:lts Dockerfile FROM jenkins/jenkins:lts USER r ...

  7. JS高级---原型的简单的语法

    原型的简单的语法 构造函数,通过原型添加方法,以下语法,手动修改构造器的指向 实例化对象,并初始化,调用方法 <!DOCTYPE html> <html lang="en& ...

  8. linux下使用crontab新建定时任务

    我安装了一个全文搜索的插件,但是需要生成索引才能使用,但是不能手动生成索引,所以说呢,我就加了一个定时任务, 一.首先vim /etc/crontab 打开文件 我根据上面的提示加了用户名,但是看到其 ...

  9. flask 前端 分页 显示

    # flask 前端 分页 显示 1.分页原理 web查询大量数据并显示时有有三种方式: 从数据库中查询全部,在view/客户端筛选/分页:不能应对记录大多的情况,一般不使用: 分页查询,每次在数据库 ...

  10. vue 中监听页面滚动

    监听页面滚动 在methods中定义一个方法 handleScroll() { //获取滚动时的高度 let scrollTop = window.pageYOffset || document.do ...