惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
L
LangChain Blog
博客园_首页
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
月光博客
月光博客
S
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
Vercel News
Vercel News
P
Privacy International News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
J
Java Code Geeks
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
有赞技术团队
有赞技术团队
A
Arctic Wolf
I
InfoQ
T
Tor Project blog
Attack and Defense Labs
Attack and Defense Labs
Microsoft Security Blog
Microsoft Security Blog
博客园 - 司徒正美
K
Kaspersky official blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recent Announcements
Recent Announcements
D
Docker
TaoSecurity Blog
TaoSecurity Blog
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
T
Troy Hunt's Blog
Help Net Security
Help Net Security
量子位
罗磊的独立博客
C
Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 【当耐特】
腾讯CDC
Webroot Blog
Webroot Blog
N
News and Events Feed by Topic
小众软件
小众软件
N
Netflix TechBlog - Medium

Java技术经验分享

生产故障处理SOP分享 | Java技术经验分享 系统稳定性建设实践总结【转载】 | Java技术经验分享 valine访问leancloud国际版异常,评论失效修复 | Java技术经验分享 匆匆忙忙的2021 | Java技术经验分享 聊一下换工作 | Java技术经验分享 IoT系列(2):WIFI设备常见配网方案介绍 | Java技术经验分享 IoT系列(1):什么是物联网 | Java技术经验分享 Java8特性2 - StreamApi | Java技术经验分享 Java8特性1 - lambda表达式&函数式接口 | Java技术经验分享 设计模式(5)-适配器模式 | Java技术经验分享 设计模式(3)-原型模式与浅拷贝和深拷贝 | Java技术经验分享 设计模式(2)-工厂模式图文介绍 | Java技术经验分享 设计模式(1)-带你了解3类8种单例模式 | Java技术经验分享 Java时间处理5---Java8中时区相关类库介绍 | Java技术经验分享 Java时间处理4---Java8中LocalDate、LocalTime、LocalDateTime介绍 | Java技术经验分享 Java时间处理3---Java8中Instant、Duration、Period、Clock介绍 | Java技术经验分享 一些有意思的问答 | Java技术经验分享 Nacos系列博客说明 | Java技术经验分享 菜鸡程序员的2019年度总结 | Java技术经验分享 Java中“附近的人”实现方案讨论及代码实现 | Java技术经验分享 Java时间处理2----时区TimeZone类方法探究(Java8以前) | Java技术经验分享 Java时间处理1----Date和Calendar方法探究(Java8以前) | Java技术经验分享 FastJson中JSONString、JavaBean、JSONObject、JSONArray的转换关系及API示例 | Java技术经验分享 2019.11软考软件设计师归来心得体会及复习备考指南 | Java技术经验分享 你还没用过“约定式提交”吗?那你赶紧来补补知识吧 | Java技术经验分享 教你如何看懂UML中的类图及类图中的关系 | Java技术经验分享 设计模式总览 | Java技术经验分享 萌新入门Github请看这里,学不会远程教 | Java技术经验分享 Hexo的工作原理探究 | Java技术经验分享 Hexo-theme-butterfly修改调整记录教程 | Java技术经验分享 排序8:基数排序 | Java技术经验分享 排序7:归并排序 | Java技术经验分享 排序6:快速排序 | Java技术经验分享 排序5:冒泡排序 | Java技术经验分享 排序4:堆排序 | Java技术经验分享 排序3:选择排序 | Java技术经验分享 排序2:希尔排序 | Java技术经验分享 排序1:直接插入排序 | Java技术经验分享 推荐一款博客一文多发的良心工具OpenWrite | Java技术经验分享 近期学习计划 | Java技术经验分享 Nacos(九):Nacos集群部署和遇到的问题 | Java技术经验分享 Nacos(八):Nacos持久化 | Java技术经验分享 Nacos(七):Nacos共享配置 | Java技术经验分享 Nacos(六):多环境下如何“管理”及“隔离”配置和服务 | Java技术经验分享 Nacos(五):多环境下如何“读取”Nacos中相应的配置 | Java技术经验分享 Nacos(四):SpringCloud项目中接入Nacos作为配置中心 | Java技术经验分享 Nacos(三):Nacos与OpenFeign的对接使用 | Java技术经验分享 Nacos(二):SpringCloud项目中接入Nacos作为注册中心 | Java技术经验分享 Nacos(一):Nacos介绍 | Java技术经验分享 20190719小组分享 | Java技术经验分享 Java中equals和HashCode方法的分析 | Java技术经验分享 Java中==和equals方法的分析 | Java技术经验分享 Java中的自动拆装箱、装箱缓存 | Java技术经验分享 About-blog | Java技术经验分享 Java中的编译、反编译和反编译工具全家桶分享 | Java技术经验分享 finalize()的生命周期(执行过程) | Java技术经验分享 Java关键字之final、finally与finalize方法 | Java技术经验分享 Java中重写、重载 | Java技术经验分享 Java中面向对象的三大特征:继承、封装、多态 | Java技术经验分享 DockerFile介绍 | Java技术经验分享 Docker环境下安装Gitlab | Java技术经验分享 Docker中私有仓库的搭建流程 | Java技术经验分享 Centos7下两种方式安装Docker-CE | Java技术经验分享 Vert.x创建一个Http服务 | Java技术经验分享 Vert.x创建TCP服务端及客户端 | Java技术经验分享 Vert.x Core(二)- Event Bus(事件总线) | Java技术经验分享 Vert.x-Core(一)- 基础篇 | Java技术经验分享 SpringBoot项目中实现国际化 | Java技术经验分享 Vert.x介绍 | Java技术经验分享 毕设选题项目本地运行环境搭建教程 | Java技术经验分享 Jupyter Notebooks的安装和使用介绍 | Java技术经验分享 算法笔试题:1元,5元,10元,20元,50元、100元面值人民币组合给定x元的问题 | Java技术经验分享 Quartz学习总结 | Java技术经验分享 SpringBoot2.x集成Redis | Java技术经验分享 SpringBoot2.x集成MongoDB | Java技术经验分享 [SpringCloud学习] - 浅谈微服务架构 | Java技术经验分享 基于hexo和coding免费搭建个人博客网站 | Java技术经验分享 Hello World | Java技术经验分享
设计模式(4)-建造者模式 | Java技术经验分享
文章作者: LarsCheng · 2020-09-29 · via Java技术经验分享

概念

软件开发过程中,复杂对象的创建步骤繁杂,这些产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。

复杂对象比如电脑、汽车、飞机、手机、冰箱…

这类产品的创建无法用前面介绍的工厂模式描述,只有建造者模式可以很好地描述该类产品的创建。

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,被称为建造者模式

建造者模式又叫生成器模式,是一种对象构建模式。

模拟场景

组装台式电脑,不同的人选择的配置和价位都不同,而且组装电脑需要的零件很多过程十分复杂。

用代码实现不同用户组装不同价位和配置的电脑

传统实现方式

根据上述场景,主要有以下几个类

  • 抽象电脑类
  • 具体电脑类A、B
  • 客户类

AbstractComputer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

public abstract class AbstractComputer {

public abstract void cpu();

public abstract void ram();

public abstract void disk();

public abstract void graphics();

public abstract void power();

public void build(){
this.cpu();
this.ram();
this.disk();
this.graphics();
this.power();
}
}

普通配置的电脑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ComputerType1 extends AbstractComputer implements Serializable {

@Override
public void cpu() {
System.out.println("安装普通cpu");
}

@Override
public void ram() {
System.out.println("安装8g内存");
}

@Override
public void disk() {
System.out.println("安装500g机械硬盘");
}

@Override
public void graphics() {
System.out.println("安装低配显卡");
}

@Override
public void power() {
System.out.println("安装普通电源");
}
}

客户类需要该配置电脑时进行构建

1
2
3
4
5
6
public class Client {
public static void main(String[] args) {
ComputerType1 computerType1 = new ComputerType1();
computerType1.build();
}
}

传统方式来实现电脑的组装流程是比较好理解的,但是电脑作为产品,组装过程与产品并没有完全解耦。

在设计模式中,有一种专门用于将产品与产品创建过程分析的方式,也叫做建造者模式

建造者模式

又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

他具有四个角色,分别为:

  • Product(产品角色): 一个具体的产品对象。
  • Builder(抽象建造者): 创建一个Product对象的各个部件指定的 接口/抽象类。
  • ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
  • Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。
    • 它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。

模拟场景

电脑城买组装台式机。

从选机到下单到装机到提货流程繁多步骤复杂,

实际的流程是客户提出机器需求,装机店老板给出配置A和B两个套餐和价位,客户下单,老板根据配置单A/B指挥装机员A/B进行装机,装机员装好机器之后,由装机店老板转交客户

根据场景分析可得如下几个角色:

  • 电脑:具体产品
  • 装机店:抽象建造者
  • 装机员A、B:具体建造者
  • 装机店老板:指挥者

代码实现

产品角色Computer定义如下

1
2
3
4
5
6
7
8
9
10

public class Computer {
private String cpu;
private String ram;
private String disk;
private String graphics;
private String power;


}

抽象建造者,定义所有建造者的基础方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class ComputerBuilder {
Computer computer = new Computer();

public abstract void cpu();

public abstract void ram();

public abstract void disk();

public abstract void graphics();

public abstract void power();

public Computer build(){
this.cpu();
this.ram();
this.disk();
this.graphics();
this.power();
return computer;
}
}

具体的建造者角色,装机员A、B,此处以A为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ComputerInstallerA extends ComputerBuilder {

@Override
public void cpu() {computer.setCpu("普通cpu");}

@Override
public void ram() {computer.setRam("4G内存");}

@Override
public void disk() {computer.setDisk("500G机械硬盘");}

@Override
public void graphics() {computer.setGraphics("集成显卡");}

@Override
public void power() {computer.setPower("普通电源");}
}

指挥者角色,装机店老板,指挥装机员进行某一配置的装机

1
2
3
4
5
6
7
8
9
10
11
12
13
public class StoreBoss {
ComputerBuilder builder = null;

public StoreBoss setBuilder(ComputerBuilder builder) {
this.builder = builder;
return this;
}

public void builder(){
Computer computer = builder.build();
System.out.println(computer.toString());
}
}

以上便是建造者模式的基础角色,编写客户类进行测试

1
2
3
4
5
6
7
8
9
10
11
public class Client {
public static void main(String[] args) {
StoreBoss boss = new StoreBoss();

System.out.println("客户A的电脑配置:");
boss.setBuilder(new ComputerInstallerA()).builder();

System.out.println("客户B的电脑配置:");
boss.setBuilder(new ComputerInstallerB()).builder();
}
}

客户只需要联系装机店老板,并告诉他自己的需求,即可进行按需装机

执行结果如下:

1
2
3
4
客户A的电脑配置:
Computer{cpu='普通cpu', ram='4G内存', disk='500G机械硬盘', graphics='集成显卡', power='普通电源'}
客户B的电脑配置:
Computer{cpu='高端cpu', ram='16G内存', disk='500G固态硬盘', graphics='GTX2080Ti显卡', power='金标550W电源'}

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

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

如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车