08.哲说建造者模式(Builder Pattern)
“The odds that we’re in ‘base reality’ is one in billions.” —— Elon Musk
这段话出自马斯克在2016年的一次演讲,“人类活在真实世界的几率,可能不到十亿分之一”。此言一出,可谓一石激起千层浪。有人嘲讽马斯克是“语不惊人死不休”,也有人对他的言论深信不疑,更多的人则是把这种言论当作茶余饭后消遣的谈资。
笔者对于 “世界是否真的真实” 这一问题的结果并不狂热,但我对于马斯克说出这句话的时间点很感兴趣,我可以帮大家捋一下前后的时间线。
2016年,ChatGPT诞生,而马斯克正是OpenAI的联合创办人之一
2017年,ChatGPT正式推出
2018年,ChatGPT开始全面发展,在社区活跃度直线上升
2019年,OpenAI从非营利性组织转型为“利润上限(caped-profit)”公司后,马斯克离开
2020年至今,ChatGPT逐渐火爆出圈,可以说改变人们的生活方式去日不远
微妙吗?“日心说” 源于计算结果,马斯克的话是否也源于即有结果的合理推测呢?这个话题可能每个人都会有自己的看法。
“天下万物生于有,有生于无。”——《道德经·第四十章》
一言
建造者模式是一步步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建他们而不需要知道内部具体的构建细节。
概述
“天下万物生于有,有生于无”。如果现在我告诉你,你可以创建一个世界,你是一个造物主,但是你要把自己藏起来,不能让这个世界的小生命知道你的存在,你会以什么样的逻辑来设计第一个模型?
有人说,我要信“码”由缰,懒得装;有人说,我要挖空细节演好上帝。
这其实就是设计模式有趣的地方,它松散无骨,语气平和,不按它的来这个世界的太阳照常升起,但按它的要求做,这个世界会和谐的像假的一样。
这一次,我想让阅读我博客的你和我一起演一次“造物主”,从神的角度,俯视设计模式中的“建造者模式”。
一个看似无关紧要且过分晦涩的概念
建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现 (属性) 的对象。
创世纪
好了,上帝们,我们开始。
我们假定创造一个世界的过程是:创建星球环境,播种生命,注入意识。但是每个世界肯定有不同的差别(作为上帝,我们不可能只创建了一个世界对不?)。那么自然有的世界的星球环境是单星结构,而有的是三体结构(很熟悉吧);生命形态肯定也不尽相同,碳基生物还是硅基生物或者其它神奇的生命体;意识就更是千变万化了。

信“码”由缰的上帝
如果我是那个只想快速完成KPI,不考虑运行后果的上帝,我可能会这样设计。

代码实现
一个抽象
public abstract class AbstractHouse {//基础环境public abstract void buildEarth();//创造生命public abstract void humanBeing();//意识觉醒public abstract void aware();//建造public void build(){buildEarth();humanBeing();aware();}
}
实现人类文明
public class HumanWorld extends AbstractHouse{@Overridepublic void buildEarth() {System.out.println("太阳系三号行星已构建");}@Overridepublic void humanBeing() {System.out.println("灵长类动物已生成");}@Overridepublic void aware() {System.out.println("人类意识觉醒,温良恭俭让");}
}
实现外星文明
public class ETWorld extends AbstractHouse{@Overridepublic void buildEarth() {System.out.println("猎户座九号行星已构建");}@Overridepublic void humanBeing() {System.out.println("硅基生物已生成");}@Overridepublic void aware() {System.out.println("异形意识觉醒,碾碎他们");}
}
经典反思
有什么问题?
优点自不必多说,两分钟的设计难度简单,易操作。
问题就是这个设计结构太简单了,上帝不会这么简单的去创建一个世界的。
没有任何的缓存层对象,程序可以说几乎没有可扩展和维护的空间。把产品(世界)和创建产品的过程(创世过程)完全封装在一起,耦合度太高了。
那么我们如何化腐朽为神奇呢?这就引出了建造者模式。
神之一手
先来了解下建造者模式的四个角色
- Product (产品角色) : 一个具体的产品对象;
- Builder (抽象建造者): 创建一个Product对象的各个部件指定的接口/抽象类;
- ConcreteBuilder (具体建造者):实现接口,构建和装配各个部件;
- Director (指挥者):构建一个Builder接口的对象,它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程;二是:负责控制产品对象的生产过程。
图解

代码
产品类
public class World{private String space;//环境private String alive;//生命private String aware;//意识//setter&getter
}
抽象建造者
public abstract class WorldBuilder {protected World world = new World();//将建造的流程写好,抽象的方法public abstract void buildEarth();public abstract void humanBeing();public abstract void aware();//建造世界,将产品返回public World build(){return world;}
}
地球文明建造者
public class EarthBuilder extends WorldBuilder{@Overridepublic void buildEarth() {System.out.println("太阳系三号行星");world.setSpace("地球");}@Overridepublic void humanBeing() {System.out.println("地球生命");world.setAlive("人类");}@Overridepublic void aware() {System.out.println("地球人意识");world.setAware("温良恭俭让");}
}
外星文明建造者
public class ETBuilder extends WorldBuilder{@Overridepublic void buildEarth() {System.out.println("猎户座九号行星");world.setSpace("赛博坦");}@Overridepublic void humanBeing() {System.out.println("外星生命");world.setAlive("硅基生物");}@Overridepublic void aware() {System.out.println("外星人意识");world.setAware("活下去,撕碎他们");}
}
指挥者
public class WorldDirector {WorldBuilder worldBuilder = null; //方式1:构造器传入 worldBuilderpublic WorldDirector (WorldBuilder worldBuilder ) {this.worldBuilder = worldBuilder ;}//方式2:通过setter 传入 worldBuilderpublic void setWorldBuilder(WorldBuilder worldBuilder ) {this.worldBuilder = worldBuilder ;}//如何建造世界的流程,交给指挥者//创世public World constructWorld(){worldBuilder.buildEarth();worldBuilder.humanBeing();worldBuilder.aware();return worldBuilder.build();}
}
测试类
public class Client {public static void main(String[] args) {WorldDirector worldDirector = new WorldDirector (new EarthBuilder());World earth = worldDirector.constructWorld();worldDirector.setWorldBuilder(new ETBuilder());World et = worldDirector.constructWorld();System.out.println("地球人基本意识:"+earth.getAware());System.out.println("外星人基本意识:"+et.getAware());}
}
测试结果

Builder Pattern在JDK源码中的应用
其实设计模式离我们的日常开发非常近,建造者模式也不例外。比如StringBuilder,从名字看也差不多能猜到coder的思想和意图。

通过阅读Appendable、AbstractStringBuilder和StringBuilder的源码,我们会发现:
- Appendable 接口定义了多个append方法(抽象方法),即Appendable 为抽象建造者,定义了抽象方法
- AbstractStringBuilder 实现了 Appendable 接口方法,这里的AbstractstringBuilder 已经是建造者,只是不能实例化
- StringBuilder 即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由 AbstractStringBuilder 完成,而StringBuilder 继承了AbstractStringBuilder
结
客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程系统扩展方便,这也符合此前我们强调过的“开闭原则”。建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑选择建造者模式是不是真的是最优解。
其实可以着重理解一下Director的构造这部分,在我看来,Builder Pattern的巧妙之处就在于它优雅的将一颗“种子”丢到了一个星球上,在“种子”发芽之前我们无需关注这颗种子的大小、品相。“万物生于有,有生于无”。
相信能耐心读到这里的同学应该会有一种奇怪的感觉,建造者模式怎么有点类似于抽象工厂模式呢?
那么抽象工厂模式是什么?工厂模式又是什么?它们和建造者模式又有什么异同呢?卖个关子,明年(下周)讲。
预祝大家新年快乐哈~
关注我,共同进步,每周至少一更,来聊的不只是代码。——Wayne
相关文章:
08.哲说建造者模式(Builder Pattern)
“The odds that we’re in ‘base reality’ is one in billions.” —— Elon Musk 这段话出自马斯克在2016年的一次演讲,“人类活在真实世界的几率,可能不到十亿分之一”。此言一出,可谓一石激起千层浪。有人嘲讽马斯克是“语不惊人死不休…...
ubuntu18.04查询实时内存、CPU占用率命令
gnome-system-monitor效果就是下面这样:...
Python计算圆的面积
Python 计算圆的面积 圆的面积公式为 : 公式中 r 为圆的半径。 # 定义一个方法来计算圆的面积 def findArea(r): PI 3.142 return PI * (r*r) # 调用方法 r float( input("请输入圆的半径:") ) print( "圆的面积为 %.3f&qu…...
(Java企业 / 公司项目)Nacos的怎么搭建多环境配置?(含相关面试题)(二)
上一篇讲了一个单体服务中配置,传统的Nacos配置但是在微服务架构当中肯定都是多环境下配置,比如生产环境,dev测试环境等等。 第一种方式模拟开始: 首先展示在生产环境中nacos如何配置,在模块下新建一个配置文件&…...
DolphinScheduler实际应用
前言 最近公司新启动了一个项目,然后领导想用一下新技术,并且为公司提供多个大数据调度解决方案,我呢就根据领导要求调研了下当前的开源调度工具,最终决定采用DolphinScheduler, 因此研究了一下DolphinScheduler &…...
P10 RV1126推流项目——ffmpeg输出参数初始化
前言 从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ 🔥 推荐专栏2: 《Linux C应用编程(概念类)_C…...
正定矩阵在格密码中的应用(知识铺垫)
目录 一. 写在前面 二. 最小值点 三. 二次型结构 四. 正定与非正定讨论 4.1 对参数a的要求 4.2 对参数c的要求 4.3 对参数b的要求 五. 最小值,最大值与奇异值 5.1 正定型(positive definite) 5.2 负定型(negative defin…...
关于使用Selenium获取网页控制台的数据
背景: 需要获取网页的控制台的数据,如下图 在此文章将使用到 Pycharm 和 Selenium4 Pycharm安装 Selenium安装 from selenium import webdriver from selenium.webdriver.common.by import By import time# 创建浏览器对象 browser webdriver.Chro…...
vue2和vue3中的路由使用及传参方式
文章目录 vue2中使用路由Vue3 中使用路由路由传参方式 Vue 2 和 Vue 3 中的路由系统有很多相似之处,但也存在一些重要的区别。下面将分别介绍 Vue 2 和 Vue 3 中的路由使用方式,并了解下它们之间的不同之处。 vue2中使用路由 在 Vue 2 中,通…...
论文管理器
论文管理器 这个论文管理器仍然存在许多漏洞。目前,通过按照一些例行程序操作,它可以正常工作。我将在有时间的时候改进代码,提供详细说明,并添加新功能。当该管理器的代码进行优化后,我会上传到github上。 一个建立…...
postfix配置tls加密
1.编译安装 编译安装openss【卸载原有openssl,然后下载新的安装,因为postfix需要新版本openssl】编译安装postfix,下面这行命令 make -f Makefile.init makefiles CCARGS"-DHAS_MYSQL -I/www/server/mysql/include -DUSE_SASL_AUTH -I/usr/include…...
虚拟专线网络(IP-VPN)
虚拟专线网络(IP-VPN),因为它的安全性和可靠性。通过亚洲领先的 IP VPN 提供商。享受更高的可管理性和可扩展性,在多个站点之间交付 IP 流量或数据包,拥有亚太地区最大的 IP 骨干网。 1,保证正常运行时间,在网络链路发…...
【Unity动画系统】Unity动画系统Animation详解,参数细节你是否弄清?
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:Uni…...
K8S Helm安装RocketMQ standalone单机版,配置外网地址注册到nameserver中方便本地开发
K8S Helm安装RocketMQ standalone单机版,配置外网地址注册到nameserver中方便本地开发 helm地址 rocketmq 3.0.2 sir5kong/rocketmq helm repo add rocketmq https://helm-charts.itboon.top/rocketmq helm pull rocketmq/rocketmq tar -xvf rocketmq-3.0.2.t…...
分布式基础概念
分布式基础概念 1 微服务 微服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API。这些服务围绕业务能力来构建,并通过完全自动化部署机制…...
蓝桥杯python比赛历届真题99道经典练习题 (89-99)
【程序89】 题目:某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下: 每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。 1.程序分析: 2.程序源代码: from sys import stdout if __n…...
蚂蚁矿机AntMiner T9+引出IO定义
这个板子只有s9的原理图参考,大部分一样但是也有很多改动。 下面是自己测出来的IO。全部为PL,没有PS引出。 共计56个引脚可用,但是不是都是完整的差分对,而且显然有些走线没办法高速跑。 测试方法 万用表先区分VCC GND和IO(对地…...
浅析 Dockerfile 构建缓存:原理与优化方法
Docker镜像的分层结构 Docker镜像是由一层一层的文件系统组成,UnionFS将这些镜像层堆叠在一起镜像层是只读的,构建完成后就不能更改了,即使在新的镜像层修改或删除了某些文件,也不会影响之前的镜像层内容用Dockerfile构建镜像时&…...
隐藏层节点数对分类准确率的影响
直线上有9个格子,4个石子, 数量 结构编号 6 0 1 1 1 1 0 0 0 0 0 5 2 1 1 1 0 1 0 0 0 0 5 1 1 0 1 1 1 0 0 0 0 4 3 1 1 0 0 1 1 0 0 0 4 4 1 0 1 0 1 1 0 0 0 3 5 1 0 1 0 1 0 1 0…...
【水浸传感器】软硬件一体水浸监测整套方案远程监测解决各种环境漏水问题
一、痛点分析 在工业生产中,水浸传感器可以安装在数据中心、半导体厂房、输油管道、车间仓库、变电室等易发生水浸的区域。一旦检测到漏水情况,立即发出信号反馈。然而,水浸传感器分散在各个地点,导致管理不集中、不便捷…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...


