秒懂设计模式--学习笔记(6)【创建篇-建造者模式】
目录
- 5、建造者模式
- 5.1 介绍
- 5.2 建造步骤的重要性
- 5.3 地产开发商的困惑
- 5.4 建筑施工方
- 5.5 工程总监
- 5.6 项目实施
- 5.7 建造者模式的各角色定义
- 5.8 建造者模式
5、建造者模式
5.1 介绍
- 建造者模式(Builder)又称为生成器模式,主要用于对复杂对象的构建、初始化
- 它可以将多个简单的组件对象按顺序一步步组装起来,最终构建成一个复杂的成品对象
- 所构建的对象一定是庞大而复杂的,并且一定是按照既定的制造工序将组件组装起来的。我们通常将负责构建这些大型对象的工程师称为建造者
- 建造者模式的主要目的在于把烦琐的构建过程从不同对象中抽离出来,使其脱离并独立于产品类与工厂类
- 最终实现用同一套标准的制造工序能够产出不同的产品
- 测试类文件
5.2 建造步骤的重要性
- 建造者面对着什么样的产品模型
- 玩家选定角色后需要对其进行初始化,假设整个过程分3个步骤完成
- 第一步,玩家需要为角色选择形象以及分配力量、灵力、体力、敏捷等属性值
- 第二步,玩家可以为角色配备不同的衣服或铠甲,低于所需力量值的铠甲则不能穿戴;
- 第三步,玩家选择手持的武器与盾牌,它同上一步一样需要满足一定的条件
- 成型的游戏角色是依靠角色对象、装备对象组装而成的,对于这种复杂对象的构建一定要依赖建造者来完成
- 建造者的制造过程不仅要分步完成,还要按照顺序进行
- 玩家选定角色后需要对其进行初始化,假设整个过程分3个步骤完成
- 建造者的各制造步骤与逻辑都应该被抽离出来独立于数据模型
- 复杂的游戏角色设定还需交给专业的建造团队去完成
5.3 地产开发商的困惑
- 严谨的设计与施工流程的把控
- 建筑物本身应该由多个组件组成,且各组件按一定工序建造,缺一不可
- 为了简化其数据模型,我们将组成建筑物的模块归纳为3个组件,分别是地基、墙体、屋顶,将它们组装起来就能形成一座建筑物
- 以List承载各组件,模拟复杂对象中各组件的顺序组装
- 分别定义各组件对应的建造方法
- 用字符串对象String来模拟各个组件对象
- 重写了toString()方法,按从大到小的组件索引顺序组装各组件,后组装的组件应先展示出来,如屋顶应该首先输出
package builder.entity;import java.util.ArrayList;
import java.util.List;/*** 数据模型-建筑物类**/
public class Building {/*** 用list来模拟建筑物组件的组装* 以List承载各组件,模拟复杂对象中各组件的顺序组装*/private List<String> buildingComponents = new ArrayList<>();// 地基public void setBasement(String basement) {this.buildingComponents.add(basement);}// 墙体public void setWall(String wall) {this.buildingComponents.add(wall);}// 屋顶public void setRoof(String roof) {this.buildingComponents.add(roof);}/*** 重写了toString()* 按从大到小的组件索引【顺序】组装各组件,后组装的组件应先展示出来,如屋顶应该首先输出* @return*/@Overridepublic String toString() {String buildingStr = "";for (int i = buildingComponents.size() -1; i >= 0; i--) {buildingStr += buildingComponents.get(i);}return buildingStr;}
}
- 下一步思考
- 怎样才能用这个复杂的类构建出一个房子对象呢?
- 首先应该调用哪个建造方法才能保证正确的建造工序,而不至于屋顶在下面,地基却跑到天上去呢
- 地基、墙体、屋顶,这些组件都去哪里找,如何建造?
5.4 建筑施工方
- 开发商规定施工方都应该至少具备三大组件的建造能力,于是施工标准公布
- 施工方接口Builder:规定了3个施工标准, 具备三大组件的建造能力
- 别墅施工方类HouseBuilder
- 多层公寓施工方类ApartmentBuilder
package builder;import builder.entity.Building;/*** 施工方接口: 规定了3个施工标准, 具备三大组件的建造能力* 建造地基* 建造墙体* 建造屋顶* 获取建筑物,以供产品的交付**/
public interface Builder {/*** 建造地基*/public void buildBasement();/*** 建造墙体*/public void buildWall();/*** 建造屋顶*/public void buildRoof();/*** 获取建筑物,以供产品的交付* @return*/public Building getBuilding();
}
package builder.impl;import builder.Builder;
import entity.Building;/*** 别墅施工方类**/
public class HouseBuilder implements Builder {private Building house;public HouseBuilder() {house = new Building();}@Overridepublic void buildBasement() {System.out.println("挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。");house.setBasement("╬╬╬╬╬╬╬╬\n");}@Overridepublic void buildWall() {System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");house.setWall("|田|田 田|\n");}@Overridepublic void buildRoof() {System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");house.setRoof("╱◥███◣\n");}@Overridepublic Building getBuilding() {return house;}
}
package builder.impl;import builder.Builder;
import builder.entity.Building;/*** 多层公寓施工方类**/
public class ApartmentBuilder implements Builder {private Building apartment;public ApartmentBuilder() {apartment = new Building();}@Overridepublic void buildBasement() {System.out.println("深挖地基,修建地下车库,部署管道、线缆、风道。");apartment.setBasement("╚═══════════╝\n");}@Overridepublic void buildWall() {System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");// 此处假设固定8层for (int i = 0; i < 8; i++) {apartment.setWall("║ □ □ □ □ ║\n");}}@Overridepublic void buildRoof() {System.out.println("封顶,部署通风井,做防水层,保温层。");apartment.setRoof("╔═══════════╗\n");}@Overridepublic Building getBuilding() {return apartment;}
}
5.5 工程总监
- 工程总监类Director: 指导施工,并把控整个施工流程
package builder;import builder.entity.Building;/*** 工程总监类: 指导施工,并把控整个施工流程**/
public class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void setBuilder(Builder builder) {this.builder = builder;}public Building direct() {System.out.println("=====工程项目启动=====");// 第一步,打好地基builder.buildBasement();// 第二步,建造框架、墙体builder.buildWall();// 第三步,封顶builder.buildRoof();System.out.println("=====工程项目竣工=====");return builder.getBuilding();}
}
- 从宏观上管理项目并指导整个施工队的建造流程
- 依次调用施工方的打地基方法buildBasement()、建造墙体方法buildWall()及建筑物封顶方法buildRoof(),保证了建筑物自下而上的建造工序
- 施工方是由外部注入的,所以工程总监并不关心是哪个施工方来造房子,更不关心施工方有什么样的建造工艺
- 但他能保证对施工工序的绝对把控,也就是说,工程总监只控制施工流程
- 实际应用中的建造流程也许会更加复杂,且组装各个组件的流程有相对【固定】的逻辑,所以可以从施工方的建造方法中抽离出来并固化在director类中
5.6 项目实施
- 开发商客户端类Client: 组建了别墅施工队并安排给工程总监进行管理
- 之后调用其指导方法拿到别墅产品
- 开发商行将工程总监管理的施工队替换为多层公寓施工方
- 最终拿到一栋八层公寓
package builder;import builder.impl.ApartmentBuilder;
import builder.impl.HouseBuilder;/*** 开发商客户端类: 组建了别墅施工队并安排=给工程总监进行管理**/
public class Client {public static void main(String[] args) {//组建别墅施工队Director director = new Director(new HouseBuilder());System.out.println(director.direct());//替换施工队,建造公寓director.setBuilder(new ApartmentBuilder());System.out.println(director.direct());}
}
- 工艺与工序
- 施工方接口对施工标准的抽象化、标准化使建造者(施工方)的建造质量达到既定要求,且使各建造者的建造“工艺”能够个性化、多态化
- 工程总监将*工作流程抽离出来独立于建造者,使建造“工序”得到统一把控
5.7 建造者模式的各角色定义
- Product(产品):复杂的产品类,构建过程相对复杂,需要其他组件组装而成。如:建筑物类Building,需要地基、墙体、屋顶等组件组成。
- Builder(建造者):建造者接口,定义了构成产品的各个组件的构建标准,通常有多个步骤。如:施工方接口Builder。
- ConcreteBuilder(建造者实现):具体的建造者实现类,可以有多种实现,负责产品的组装但不包含整体建造逻辑,如:别墅施工方类HouseBuilder与多层公寓施工方类ApartmentBuilder
- Director(指导者):持有建造者接口引用的指导者类,指导建造者按一定的逻辑进行建造。如:工程总监类Director。
5.8 建造者模式
- 复杂对象的构建显然需要专业的建造团队
- 建造标准的确立让产品趋向多样化
- 而建造工序则交由工程总监去全局把控
- 最终实现通过相同的构建过程生产出不同产品
相关文章:

秒懂设计模式--学习笔记(6)【创建篇-建造者模式】
目录 5、建造者模式5.1 介绍5.2 建造步骤的重要性5.3 地产开发商的困惑5.4 建筑施工方5.5 工程总监5.6 项目实施5.7 建造者模式的各角色定义5.8 建造者模式 5、建造者模式 5.1 介绍 建造者模式(Builder)又称为生成器模式,主要用于对复杂对象…...

领略超越王勃的AI颂扬艺术:一睹其惊艳夸赞风采
今日,咱也用国产AI技术,文心一言3.5的文字生成与可灵的图像创作,自动生成一篇文章,提示语文章末下载。 【玄武剑颂星际墨侠】 苍穹为布,星辰织锦,世间万象,皆入我玄武剑公众号之浩瀚画卷。此号…...

Linux走进网络
走进网络之网络解析 目录 走进网络之网络解析 一、认识计算机 1.计算机的发展 2.传输介质 3.客户端与服务器端的概念 交换机 路由器 二、计算机通信与协议 1. 协议的标准化 2. 数据包的传输过程 OSI 协议 ARP协议 3. TCP/IP:四层模型 4. TCP三次握手和四次挥手…...

go语言Gin框架的学习路线(六)
gin的路由器 Gin 是一个用 Go (Golang) 编写的 Web 框架,以其高性能和快速路由能力而闻名。在 Gin 中,路由器是框架的核心组件之一,负责处理 HTTP 请求并将其映射到相应的处理函数上。 以下是 Gin 路由器的一些关键特性和工作原理的简要解释…...

Java面经知识点汇总版
Java面经知识点汇总版 算法 14. 最长公共前缀(写出来即可) Java 计算机基础 数据库 基础 SQL SELECT first_name, last_name, salary FROM employees WHERE department Sales AND salary > (SELECT AVG(salary)FROM employeesWHERE department Sal…...

详细分析Sql Server中的declare基本知识
目录 前言1. 基本知识2. Demo3. 拓展Mysql4. 彩蛋 前言 实战探讨主要来源于触发器的Demo 1. 基本知识 DECLARE 语句用于声明变量 声明的变量可以用于存储临时数据,并在 SQL 查询中多次引用 声明变量:使用 DECLARE 语句声明一个或多个变量变量命名&a…...

Perl 语言入门:编写并执行你的第一个脚本
摘要 Perl 是一种高级、通用的、解释型、动态编程语言,以其强大的文本处理能力而闻名。本文将指导初学者如何编写和执行他们的第一个 Perl 脚本,包括 Perl 的基本概念、脚本的基本结构、运行 Perl 脚本的方法以及一些简单的 Perl 语法。 引言 Perl&am…...

python库 - missingno
missingno 是一个用于可视化和分析数据集中缺失值的 Python 库。它提供了一系列简单而强大的工具,帮助用户直观地理解数据中的缺失模式,从而更好地进行数据清洗和预处理。missingno 库特别适用于数据分析和数据科学项目,尤其是在处理缺失数据…...

VPN的限制使得WinSCP无法直接连接到FTP服务器解决办法
由于VPN的限制使得WinSCP无法直接连接到FTP服务器,并且堡垒机的文件上传限制为500M,因此我们需要找到一种绕过这些限制的方法。以下是几个可行的方案: 方法1:通过分割文件上传 分割文件: 使用文件分割工具(…...

PCI DSS是什么?
PCI DSS,全称为Payment Card Industry Data Security Standard(支付卡行业数据安全标准),是由支付卡行业安全标准委员会(PCI Security Standards Council)制定的一套安全标准,旨在保护信用卡信息…...

DeepMind的JEST技术:AI训练速度提升13倍,能效增强10倍,引领绿色AI革命
谷歌旗下的人工智能研究实验室DeepMind发布了一项关于人工智能模型训练的新研究成果,声称其新提出的“联合示例选择”(Joint Example Selection,简称JEST)技术能够极大地提高训练速度和能源效率,相比其他方法ÿ…...

如何使用 pytorch 创建一个神经网络
我已发布在:如何使用 pytorch 创建一个神经网络 SapientialM.Github.io 构建神经网络 1 导入所需包 import os import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms2 检查GPU是否可用 dev…...

Java版Flink使用指南——定制RabbitMQ数据源的序列化器
大纲 新建工程新增依赖数据对象序列化器接入数据源 测试修改Slot个数打包、提交、运行 工程代码 在《Java版Flink使用指南——从RabbitMQ中队列中接入消息流》一文中,我们从RabbitMQ队列中读取了字符串型数据。如果我们希望读取的数据被自动化转换为一个对象&#x…...

CV每日论文--2024.7.8
1、DisCo-Diff: Enhancing Continuous Diffusion Models with Discrete Latents 中文标题:DisCo-Diff:利用离散潜伏增强连续扩散模型 简介:这篇文章提出了一种新型的离散-连续潜变量扩散模型(DisCo-Diff),旨在改善传统扩散模型(DMs)存在的问…...

【AI大模型】赋能儿童安全:楼层与室内定位实践与未来发展
文章目录 引言第一章:AI与室内定位技术1.1 AI技术概述1.2 室内定位技术概述1.3 楼层定位的挑战与解决方案 第二章:儿童定位与安全监控的需求2.1 儿童安全问题的现状2.2 智能穿戴设备的兴起 第三章:技术实现细节3.1 硬件设计与选择传感器选择与…...

云服务器linux系统安装配置docker
在我们拿到一个纯净的linux系统时,我需要进行一些基础环境的配置 (如果是云服务器可以用XShell远程连接,如果连接不上可能是服务器没开放22端口) 下面是配置环境的步骤 sudo -s进入root权限:退出使用exit sudo -i进入…...

泰勒雷达图2
matplotlib绘制泰勒雷达图 import matplotlib.pyplot as plt import numpy as np from numpy.core.fromnumeric import shape import pandas as pd import dask.dataframe as dd from matplotlib.projections import PolarAxes import mpl_toolkits.axisartist.floating_axes a…...

数据库容灾 | MySQL MGR与阿里云PolarDB-X Paxos的深度对比
开源生态 众所周知,MySQL主备库(两节点)一般通过异步复制、半同步复制(Semi-Sync)来实现数据高可用,但主备架构在机房网络故障、主机hang住等异常场景下,HA切换后大概率就会出现数据不一致的问…...

react根据后端返回数据动态添加路由
以下代码都为部分核心代码 一.根据不同的登录用户,返回不同的权限列表 ,以下是三种不同用户限权列表 const pression { //超级管理员BigAdmin: [{key: "screen",icon: "FileOutlined",label: "数据图表",},{key: "…...

机器学习中的可解释性
「AI秘籍」系列课程: 人工智能应用数学基础 人工智能Python基础 人工智能基础核心知识 人工智能BI核心知识 人工智能CV核心知识 为什么我们需要了解模型如何进行预测 我们是否应该始终信任表现良好的模型?模型可能会拒绝你的抵押贷款申请或诊断你患…...

上海慕尼黑电子展开展,启明智显携物联网前沿方案亮相
随着科技创新的浪潮不断涌来,上海慕尼黑电子展在万众瞩目中盛大开幕。本次展会汇聚了全球顶尖的电子产品与技术解决方案,成为业界瞩目的焦点。启明智显作为物联网彩屏显示领域的佼佼者携产品亮相展会,为参展者带来了RTOS、LINUX全系列方案及A…...

Centos7离线安装ElasticSearch7.4.2
一、官网下载相关的安装包 ElasticSearch7.4.2: elasticsearch-7.4.2-linux-x86_64.tar.gz 下载中文分词器: elasticsearch-analysis-ik-7.4.2.zip 二、上传解压文件到服务器 上传到目录:/home/data/elasticsearch 解压文件࿱…...

深入理解sklearn中的模型参数优化技术
参数优化是机器学习中的关键步骤,它直接影响模型的性能和泛化能力。在sklearn中,参数优化可以通过多种方式实现,包括网格搜索(GridSearchCV)、随机搜索(RandomizedSearchCV)和贝叶斯优化等。本文…...

【Elasticsearch】开源搜索技术的演进与选择:Elasticsearch 与 OpenSearch
开源搜索技术的演进与选择:Elasticsearch 与 OpenSearch 1.历史发展2.OpenSearch 与 Elasticsearch 相同点3.OpenSearch 与 Elasticsearch 不同点3.1 版本大不同3.2 许可证不同3.3 社区不同3.4 功能不同3.5 安全性不同3.6 性能不同3.7 价格不同3.8 两者可相互导入 4…...

欧拉openEuler 22.03 LTS-部署k8sv1.03.1
1.设置ip # vi /etc/sysconfig/network-scripts/ifcfg-ens32 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DEFROUTEyes IPV4_FAILURE_FATALno #IPV6INITyes #IPV6_AUTOCONFyes #IPV6_DEFROUTEyes #IPV6_FAILURE_FATALno #IPV6_ADDR_GEN_MODEeui64 NAMEens1…...

老年生活照护实训室:为养老服务业输送专业人才
本文探讨了老年生活照护实训室在养老服务业专业人才培养中的关键作用。通过详细阐述实训室的功能、教学实践、对学生能力的培养以及面临的挑战和解决方案,强调了其在提升人才素质、满足行业需求方面的重要性,旨在为养老服务业的可持续发展提供有力的人才…...

go语言中使用WaitGroup和channel实现处理多线程问题
WaitGroup 背景 如果将一个任务分为任意个小任务,并且不关心小任务的执行顺序,并且希望等待全部的小任务执行完成后再去操作后面的逻辑,那我推荐你用sync.WaitGRoup 使用方法 比如,有一个任务需要执行 3 个子任务,…...

Open3D 计算点云的平均密度
目录 一、概述 1.1基于领域密度计算原理 1.2应用 二、代码实现 三、实现效果 2.1点云显示 2.2密度计算结果 一、概述 在点云处理中,点的密度通常表示为某个点周围一定区域内的点的数量。高密度区域表示点云较密集,低密度区域表示点云较稀疏。计算…...

C语言之数据在内存中的存储(1),整形与大小端字节序
目录 前言 一、整形数据在内存中的存储 二、大小端字节序 三、大小端字节序的判断 四、字符型数据在内存中的存储 总结 前言 本文主要讲述整型包括字符型是如何在内存中存储的,涉及到大小端字节序这一概念,还有如何判断大小端,希望对大…...

B端全局导航:左侧还是顶部?不是随随便便,有依据在。
一、什么是全局导航 B端系统的全局导航是指在B端系统中的主要导航菜单,它通常位于系统的顶部或左侧,提供了系统中各个模块和功能的入口。全局导航菜单可以帮助用户快速找到和访问系统中的各个功能模块,提高系统的可用性和用户体验。 全局导航…...