秒懂设计模式--学习笔记(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核心知识 为什么我们需要了解模型如何进行预测 我们是否应该始终信任表现良好的模型?模型可能会拒绝你的抵押贷款申请或诊断你患…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
