建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式

​ 使用多个简单的对象一步一步构建成一个复杂的对象。有点像造房子一样,一步一步从地基到万丈高楼。

概念

  1. 定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示!
  2. 主要作用在用户不知道 对象的建造过程和细节 的情况下就可以直接创建复杂的对象。
  3. 如何使用用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建负责对象(把内部的建造过程和细节隐藏起来)。
  4. 解决的问题:
    1. 方便用户创建负责的对象(不需要知道实现过程)
    2. 代码复用性 & 封装性(将对象构建过程和细节进行封装 & 复用)

注意事项:与工厂模式的区别是:建造者模式更加关注零件的装配顺序,一般用来创建更为复杂的对象。

角色分析

  • 指挥者(Director)直接和客户(Client)进行需求沟通;
  • 沟通后指挥者将客户创建产品的需求划分为各个部件的建造请求(Builder);
  • 将各个部件的建造请求委派到具体的建造者(ConcreteBuilder);
  • 各个具体建造者负责进行产品部件的构建;
  • 最终构建成具体产品(Product)。

实现方式

  • 方式一:通过Client、Director、Builder、Produce形成的建造者模式

  • 方式二:通过静态内部类方式实现零件无序装配化构造

方式一

​ 通过Client、Director、Builder、Produce形成的建造者模式,该模式就像是造房子一样,你要造一个房子(产品),要去找包工头(指挥者),包工头根据造房子的步骤图纸(抽象的构建者)来分配任务,负责指挥工人(具体的构建者)工作。

角色分析

  1. 抽象建造者(builder):描述具体建造者的公共接口,一般用来定义建造细节的方法,并不涉及具体的对象部件的创建。
  2. 具体建造者(ConcreteBuilder):描述具体建造者,并实现抽象建造者公共接口。
  3. 指挥者(Director):调用具体建造者来创建复杂对象(产品)的各个部分,并按照一定顺序(流程)来建造复杂对象。
  4. 产品(Product):描述一个由一系列部件组成较为复杂的对象。

代码编写

/**
* 抽象的构建者:获取产品的步骤
*/
public abstract class AbstractBuilder { // 地基
abstract void buildA();
// 钢筋水泥
abstract void buildB();
// 铺电线
abstract void buildC();
// 粉刷
abstract void buildD(); // 获取产品,完工
abstract Product getProduct();
}
/**
* 产品:房子
*/
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD; @Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
} public void setBuildA(String buildA) {
this.buildA = buildA;
} public void setBuildB(String buildB) {
this.buildB = buildB;
} public void setBuildC(String buildC) {
this.buildC = buildC;
} public void setBuildD(String buildD) {
this.buildD = buildD;
}
}
/**
* 具体的构建者:工人
*/
public class Worker extends AbstractBuilder {
// 具体构建者生产的产品
Product product; public Worker() {
// 工人自己去生产产品
product = new Product();
} @Override
void buildA() {
product.setBuildA("地基");
System.out.println("地基");
} @Override
void buildB() {
product.setBuildB("钢筋工程");
System.out.println("钢筋工程"); } @Override
void buildC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
} @Override
void buildD() {
product.setBuildD("粉刷");
System.out.println("粉刷"); } // 返回具体的产品
@Override
Product getProduct() {
return product;
}
}
/**
* 指挥者:核心。
* 由它来指挥构建具体的工程,工程的构建次序由它来决定
*/
public class Director { // 指挥工人按顺序造房,指挥者可以随意控制建造的顺序!
public Product build(AbstractBuilder builder) {
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD(); return builder.getProduct();
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// 创建指挥者
Director director = new Director();
// 指挥者指挥工人建造房子,并获取产品
Product product = director.build(new Worker()); System.out.println(product);
}
} /*
输出结果:
地基
铺电线
地基
粉刷
Product{buildA='地基', buildB='钢筋工程', buildC='铺电线', buildD='粉刷'}
*/

方式二

​ 通过静态内部类方式实现零件无序装配化构造,该方式使用起来更加灵活,使用时可以根据用户的需求自定义更改内容,并且无需改变具体的构造方式。就可以生产出不同的产品。

​ 就像是你去麦当劳买东西吃一样,当服务员(具体的构建者)给你一个菜单(抽象的构构建者),问你(指挥者)要点什么时,你可以选择一整套套餐(默认产品),也可以自己喜欢什么就吃什么(自定义产品)。

角色分析

  1. 抽象建造者
  2. 具体建造者
  3. 产品

​ 比第一种方式少了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加灵活。

代码编写

/**
* 抽象的构建者:
*/
public abstract class AbstractBuilder { // 修改默认的套餐,也就是客户自己点餐
public abstract AbstractBuilder buildA(String msg); public abstract AbstractBuilder buildB(String msg); public abstract AbstractBuilder buildC(String msg); public abstract AbstractBuilder buildD(String msg); // 获取产品
public abstract Product getProduct();
}
/**
* 产品:麦当劳套餐
*/
public class Product {
// 默认的套餐
private String buildA = "汉堡";
private String buildB = "可乐";
private String buildC = "鸡翅";
private String buildD = "鸡蛋灌饼"; @Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
} public String getBuildA() {
return buildA;
} public void setBuildA(String buildA) {
this.buildA = buildA;
} public String getBuildB() {
return buildB;
} public void setBuildB(String buildB) {
this.buildB = buildB;
} public String getBuildC() {
return buildC;
} public void setBuildC(String buildC) {
this.buildC = buildC;
} public String getBuildD() {
return buildD;
} public void setBuildD(String buildD) {
this.buildD = buildD;
}
}
/**
* 具体的建造者:服务员
*/
public class Worker extends AbstractBuilder {
private Product product; public Worker() {
product = new Product();
} @Override
public AbstractBuilder buildA(String msg) {
product.setBuildA(msg);
return this;
} @Override
public AbstractBuilder buildB(String msg) {
product.setBuildB(msg);
return this;
} @Override
public AbstractBuilder buildC(String msg) {
product.setBuildC(msg);
return this;
} @Override
public AbstractBuilder buildD(String msg) {
product.setBuildD(msg);
return this;
} @Override
public Product getProduct() {
return product;
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// 创建服务员
Worker worker = new Worker();
// 链式编程,客户自己点套餐,不需要指挥者,用户本身就是指挥者
Product product = worker
.buildA("烤冷面")
.buildB("雪碧")
.buildC("")
.buildD("")
.getProduct();
System.out.println(product);
// Product{buildA='烤冷面', buildB='雪碧', buildC='', buildD=''}
}
} /*
输出结果:
Product{buildA='烤冷面', buildB='雪碧', buildC='', buildD=''}
*/

总结

优点

  1. 产品的建造与表示分离,实现了解耦,使用建造者模式可以使客户端不必知道产品内部的组成细节。
  2. 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
  3. 具体的建造者类之间是相互独立的,这有利于系统的扩展。也就是说,增加新的具体建造者无需修改原有类库的代码,符合开闭原则
  4. 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。

缺点

  1. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  2. 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

应用场景

  1. 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
  2. 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
  3. 需要生成的对象内部属性本身相互依赖
  4. 适合于一个具有较多的零件(属性)的产品(对象)的创建过程。

建造者也抽象工厂模式的比较

  • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 。
  • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车!

GoF23:建造者模式的更多相关文章

  1. 设计模式之GOF23建造者模式

    组件很多,装配顺序不定 本质: 1,分离了对象子组件的单独构造(Builder负责)和装配(Director负责),从而可以构造出复杂的对象,这个模式适用于某个对象的构建过程复杂的情况下使用 2,实现 ...

  2. 【GOF23设计模式】建造者模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]建造者模式详解类图关系 建造飞船 package com.test.Builder; public class AirShi ...

  3. GOF23设计模式之建造者模式

    GOF23设计模式之建造者模式 场景: 我们要建造一个复杂的产品.比如:神州飞船,Iphone.这个复杂的产品的创建.有这样的一个问题需要处理: 装配这些子组件是不是有个步骤问题? 实际开发中,我们所 ...

  4. GOF23设计模式之建造者模式(builder)

    一.建造者模式概述 建造者模式的本质: 1.分离了对象子组件的单独构造(由Builder负责)和装配(由Director负责).从而可以构造出复杂的对象.这个模式适用于:某个对象的过程复杂的情况下使用 ...

  5. C#设计模式之四建造者模式(Builder Pattern)【创建型】

    一.引言 今天我们要讲讲Builder模式,也就是建造者模式,当然也有叫生成器模式的,英文名称是Builder Pattern.在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:电脑,它就是一 ...

  6. 建造者模式(Builder和Director)

    一.建造者模式介绍 建造者模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. [构建与表示分离,同构建不同表示] 假如一个对象的构建很复杂,需要很多步骤.则可以使用建造者模式 ...

  7. C#设计模式学习笔记:(4)建造者模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7614630.html,记录一下学习过程以备后续查用. 一.引言 在现实生活中,我们经常会遇到一些构成比较复杂 ...

  8. 23种设计模式--建造者模式-Builder Pattern

    一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建 ...

  9. PHP设计模式(五)建造者模式(Builder For PHP)

    建造者模式:将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示的设计模式. 设计场景: 有一个用户的UserInfo类,创建这个类,需要创建用户的姓名,年龄,爱好等信息,才能获得用 ...

随机推荐

  1. [译]HAL-超文本应用语言

    [译]HAL-超文本应用语言 精益超媒体类型 总结 HAL 是一种简单的格式,它提供了一种一致且简便的方法在 API 的资源之间进行超链接. 采用 HAL 将使您的 API 易于探索,并且其文档很容易 ...

  2. Java接口和抽象类有什么区别,哪些时候用接口,哪些时候用抽象类?

    Java接口和抽象类有什么区别,哪些时候用接口,哪些时候用抽象类? 2013-01-05 17:16:09|  分类: JAVA |  标签:java  |举报|字号 订阅     下面比较一下两者的 ...

  3. 用一个完整的案例讲解Python数据分析的整个流程和基础知识

    先来想一下数据分析的流程,第一步获取数据,因此本节内容就是获取数据以及对数据的基本操作. 1.数据导入 1.1 导入.xlsx文件 要导入一个.xlsx后缀的Excel文件,可以使用pd.read_e ...

  4. 小说光看还不够?用Python做有声小说!

    文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http:// ...

  5. 文件密码忘记了怎么办,教你如何使用Python破解密码

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:轻松学编程小梁 PS:如有需要Python学习资料的小伙伴可以加点击下 ...

  6. 原创zookeeper3.4.6集群安装

    tar -zxvf zookeeper-3.4.6.tar.gz -C /home/hadoop/ vi ~/.bash_profile export ZOOKEEPER_HOME=/home/had ...

  7. Nginx知多少系列之(七)负载均衡策略

    目录 1.前言 2.安装 3.配置文件详解 4.工作原理 5.Linux下托管.NET Core项目 6.Linux下.NET Core项目负载均衡 7.负载均衡策略 8.加权轮询(round rob ...

  8. 3. git获取历史版本

    1.使用gitbash进入git命令行,查看commit记录.操作如下: git log 1 2.找到你想提取的目标版本,复制对应的SHA值. 3.新建一个分支,操作如下: git branch 新分 ...

  9. Everything信息泄露

    Everything漏洞描述 [Everything]一款搜索文件非常快的工具,其速度之快令人震惊!它还有一个可以通过HTTP 或 FTP 分享搜索结果 的功能.它可以让用户在本地或局域网上的其他电脑 ...

  10. python里的内置函数你知道有多少个吗?

    Python 内置函数最全汇总: 1 abs() 绝对值或复数的模 2 all() 接受一个迭代器,如果迭代器的所有元素都为真,那么返回True,否则返回False 3 any() 接受一个迭代器,如 ...