【设计模式-2.5】创建型——建造者模式
说明:本文介绍设计模式中,创建型设计模式中的最后一个,建造者模式;
入学报道
创建型模式,关注于对象的创建,建造者模式也不例外。假设现在有一个场景,高校开学,学生、教师、职工都要办理相关的报道手续,如签到、个人信息录入、分配身份证明(学生证、教师证、职工证)等等;
首先,创建一个抽象类,如下:
(Person,人员类,有签到、个人信息、身份证明属性)
/*** 人员*/
public class Person {/*** 签到*/private String signIn;/*** 个人信息*/private String profile;/*** 身份证明*/private String idCard;public String getSignIn() {return signIn;}public void setSignIn(String signIn) {this.signIn = signIn;}public String getProfile() {return profile;}public void setProfile(String profile) {this.profile = profile;}public String getIdCard() {return idCard;}public void setIdCard(String idCard) {this.idCard = idCard;}
}
在创建具体对象之前,先创建一个抽象的建造者类,用于统一方法,定义人员对象;
(PersonBuilder,人员建造者)
/*** 抽象建造者*/
public abstract class PersonBuilder {Person person = new Person();/*** 签到行为*/public abstract void buildSignIn();/*** 录入个人信息*/public abstract void buildProfile();/*** 办理身份证明*/public abstract void buildIdCard();/*** 建造完成* @return*/public Person build() {return person;}
}
(Student,学生类,继承人员建造者,重写学生入学相关方法)
/*** 学生入学*/
public class Student extends PersonBuilder {@Overridepublic void buildSignIn() {person.setSignIn("学生已签到");}@Overridepublic void buildProfile() {person.setProfile("学生信息已录入");}@Overridepublic void buildIdCard() {person.setIdCard("学生证已办理");}
}
(Teacher,教师类,继承人员建造者,重写教师入学相关方法)
/*** 教师入学*/
public class Teacher extends PersonBuilder {@Overridepublic void buildSignIn() {person.setSignIn("老师已签到");}@Overridepublic void buildProfile() {person.setProfile("老师个人信息已录入");}@Overridepublic void buildIdCard() {person.setIdCard("老师身份证已办理");}
}
(Employee,职工类,继承人员建造者,重写职工入学相关方法)
/*** 职工入学*/
public class Employee extends PersonBuilder {@Overridepublic void buildSignIn() {person.setSignIn("员工已签到");}@Overridepublic void buildProfile() {person.setProfile("员工个人信息已录入");}@Overridepublic void buildIdCard() {person.setIdCard("员工身份证已办理");}
}
再创建一个建造者控制类,协调入学后的具体事宜,如先签到、后录入个人信息,最后才发身份证明,返回建造完成的人员对象;
(PersonController,人员入学控制器)
/*** 人员入学控制器*/
public class PersonController {/*** 人员入学* @return*/public Person construct(PersonBuilder personBuilder) {personBuilder.buildSignIn();personBuilder.buildProfile();personBuilder.buildIdCard();return personBuilder.build();}
}
(Client,客户端,演示人员入学过程)
/*** 客户端*/
public class Client {public static void main(String[] args) {// 一个学生入学Person student = new PersonController().construct(new Student());System.out.println(student.getSignIn());System.out.println(student.getProfile());System.out.println(student.getIdCard());System.out.println("=====================================");// 一个老师入学Person teacher = new PersonController().construct(new Teacher());System.out.println(teacher.getSignIn());System.out.println(teacher.getProfile());System.out.println(teacher.getIdCard());}
}
(执行结果,可见对象已创建完成)

改进与优化
在《设计模式的艺术》(第一版,刘伟著)中,作者关于PersonController(人员控制器)类的作用,有两点改进与优化的地方,如下:
改进:可省略PersonController
可在抽象建造者类PersonBuilder(人员建造者)中定义一个静态的Person变量,这样就不需要额外设立一个PersonController类了,如下:
(PersonBuilder,抽象人员建造者,既统一了方法,也完成了建造的流程)
/*** 抽象建造者*/
public abstract class PersonBuilder {/*** 定义一个抽象的Person*/protected static Person person = new Person();/*** 签到行为*/public abstract void buildSignIn();/*** 录入个人信息*/public abstract void buildProfile();/*** 办理身份证明*/public abstract void buildIdCard();/*** 建造Person* @return*/public static Person build(PersonBuilder personBuilder) {personBuilder.buildSignIn();personBuilder.buildProfile();personBuilder.buildIdCard();return person;}
}
(Client,客户端,使用人员建造者的build()方法建造对象)
/*** 客户端*/
public class Client {public static void main(String[] args) {// 一个学生入学Person student = PersonBuilder.build(new Student());System.out.println(student.getSignIn());System.out.println(student.getProfile());System.out.println(student.getIdCard());System.out.println("=====================================");// 一个老师入学Person teacher = PersonBuilder.build(new Teacher());System.out.println(teacher.getSignIn());System.out.println(teacher.getProfile());System.out.println(teacher.getIdCard());}
}
(执行效果相同)

优化:细化建造过程
可以定义一个“钩子”方法,“钩子”方法一般是“isXXX”命名的,返回值为boolean类型。利用“钩子”方法,规定某些人员可以跳过或者必须执行某方法,来细化对象建造的流程。如规定教师人员的建造,因为教师流动不大,可以跳过录入信息流程。
就可以在PersonBuilder类中定义一个“钩子”方法,默认返回true,即默认所有人员都需要录入个人信息。如下:
/*** 抽象建造者*/
public abstract class PersonBuilder {/*** 定义一个抽象的Person*/protected static Person person = new Person();/*** 签到行为*/public abstract void buildSignIn();/*** 录入个人信息*/public abstract void buildProfile();/*** 办理身份证明*/public abstract void buildIdCard();/*** 钩子方法:表示默认所有人都需要经过buildProfile()方法,具体由子类实现*/public boolean isBuildProfile() {return true;}/*** 建造Person* @return*/public static Person build(PersonBuilder personBuilder) {personBuilder.buildSignIn();// 根据钩子方法判断是否需要buildProfile()if (personBuilder.isBuildProfile()) {personBuilder.buildProfile();}personBuilder.buildIdCard();return person;}
}
教师类中,可以重写这个“钩子”方法,表示不需要执行录入个人信息这个流程了。
/*** 教师入学*/
public class Teacher extends PersonBuilder {@Overridepublic void buildSignIn() {person.setSignIn("老师已签到");}@Overridepublic void buildProfile() {person.setProfile("老师个人信息已录入");}@Overridepublic void buildIdCard() {person.setIdCard("老师身份证已办理");}@Overridepublic boolean isBuildProfile() {return false;}
}
客户端代码不变,执行
/*** 客户端*/
public class Client {public static void main(String[] args) {// 一个学生入学Person student = PersonBuilder.build(new Student());System.out.println(student.getSignIn());System.out.println(student.getProfile());System.out.println(student.getIdCard());System.out.println("=====================================");// 一个老师入学Person teacher = PersonBuilder.build(new Teacher());System.out.println(teacher.getSignIn());System.out.println(teacher.getProfile());System.out.println(teacher.getIdCard());}
}
执行结果可以看到教师确实是没有执行录入个人信息的方法,但是因为Person是static修饰的属性,打印的是上面学生的值。

那么,如果避免这个问题值得思考,或者就不省略PersonController类。
小结
建造者模式,通过定义一个抽象建造者类,封装了对象创建的细节,另外通过“钩子”方法,可细化对象创建过程,降低了系统复杂度,维护了系统的灵活性和扩展性。
总结
本文参考《设计模式的艺术》、《秒懂设计模式》两书
相关文章:
【设计模式-2.5】创建型——建造者模式
说明:本文介绍设计模式中,创建型设计模式中的最后一个,建造者模式; 入学报道 创建型模式,关注于对象的创建,建造者模式也不例外。假设现在有一个场景,高校开学,学生、教师、职工都…...
VideoPoet: Google的一种用于零样本视频生成的大型语言模型
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
pytest常用命令行参数
文章目录 一、前置说明二、操作步骤1. 命令行中执行:pytest2. 命令行中执行:pytest - v3. 命令行中执行:pytest -s4. 命令行中执行:pytest -k test_addition5. 命令行中执行:pytest -k test_pytest_command_params.py6. 命令行中执行:pytest -v -s -k test_pytest_comman…...
05. Springboot admin集成Actuator(一)
目录 1、前言 2、Actuator监控端点 2.1、健康检查 2.2、信息端点 2.3、环境信息 2.4、度量指标 2.5、日志文件查看 2.6、追踪信息 2.7、Beans信息 2.8、Mappings信息 3、快速使用 2.1、添加依赖 2.2、添加配置文件 2.3、启动程序 4、自定义端点Endpoint 5、自定…...
AI生成SolidUI-新版本架构调试Debug
背景 SolidUI 0.5.0 版本重构全新版本架构。 dev-python 新架构临时分支,架构调整完后,所有代码合并到dev分支 https://github.com/CloudOrc/SolidUI 使用 设置参数 FLASK_DEBUG 设置 在开发过程中,Web框架的服务器通常会监视代码的变…...
ctfshow sql 195-200
195 堆叠注入 十六进制 if(preg_match(/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\|\"|select|union|or|and|\x26|\x7c|file|into/i, $username)){$ret[msg]用户名非法;die(json_encode($ret));}可以看到没被过滤,select 空格 被过滤了,可…...
微信小程序实现地图功能(腾讯地图)
微信小程序实现地图功能(腾讯地图) 主要功能 通过微信 API 获取用户当前位置信息 使用腾讯地图 API 将经纬度转换为地址信息 显示当前位置信息以及周围的 POI(兴趣点) 代码实现 index.wxml <!-- index.wxml --> <view class"container&…...
Vue如何请求接口——axios请求
1、安装axios 在cmd或powershell打开文件后,输入下面的命令 npm install axios 可在项目框架中的package.json中查看是否: 二、引用axios import axios from axios 在需要使用的页面中引用 三、get方式使用 get请求使用params传参,本文只列举常用参数…...
【数据结构一】初始Java集合框架(前置知识)
Java中的数据结构 Java语言在设计之初有一个非常重要的理念便是:write once,run anywhere!所以Java中的数据结构是已经被设计者封装好的了,我们只需要实例化出想使用的对象,便可以操作相应的数据结构了,本篇…...
直接将第三方数据插入到 Redis 中
Redis 是一个内存数据库,可以用于缓存和持久化数据。虽然常见的使用场景是将数据从关系型数据库(如MySQL)同步到 Redis 中进行缓存,但也可以直接将第三方数据插入到 Redis 中。 你可以通过编程语言的 Redis 客户端库(…...
【重点】【DP】322.零钱兑换
题目 法1:动态规划 // 时间复杂度:O(kN) class Solution {public int coinChange(int[] coins, int amount) {int[] dp new int[amount 1];Arrays.fill(dp, amount 1);dp[0] 0;for (int i 1; i < dp.length; i) {for (int coin : coins) {if (…...
Python入门学习篇(六)——for循环while循环
1 for循环 1.1 常规for循环 1.1.1 语法结构 for 变量名 in 可迭代对象:# 遍历对象时执行的代码 else:# 当for循环全部正常运行完(没有报错和执行break)后执行的代码1.1.2 示例代码 print("----->学生检查系统<------") student_lists["张三",&qu…...
el-table 实现行拖拽排序
element ui 表格实现拖拽排序的功能,可以借助第三方插件Sortablejs来实现。 引入sortablejs npm install sortablejs --save组件中使用 import Sortable from sortablejs;<el-table ref"el-table":data"listData" row-key"id" …...
2. 结构型模式 - 桥接模式
亦称: Bridge 意图 桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用 问题 抽象? 实现? 听上去挺吓人? 让我们慢慢来&#x…...
最小二乘法简介
最小二乘法简介 1、背景描述2、最小二乘法2.1、最小二乘准则2.2、最小二乘法 3、最小二乘法与线性回归3.1、最小二乘法与线性回归3.2、最小二乘法与最大似然估计 4、正态分布(高斯分布) 1、背景描述 在工程应用中,我们通常会用一组观测数据去…...
mathtype公式章节编号
1. word每章标题后插入章节符 如果插入后显示章节符,需要进行隐藏 开始->样式->MTEquationSection->修改样式->字体,勾选隐藏 2. 设置mathtype公式编号格式 插入编号->格式化->设置格式...
医学实验室检验科LIS信息系统源码
实验室信息管理是专为医院检验科设计的一套实验室信息管理系统,能将实验仪器与计算机组成网络,使病人样品登录、实验数据存取、报告审核、打印分发,实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。 实验室管理系统功能介…...
无需改动现有网络,企业高速远程访问内网Linux服务器
某企业为数据治理工具盒厂商,帮助客户摆脱数据问题困扰、轻松使用数据,使得客户可以把更多精力投入至数据应用及业务赋能,让数据充分发挥其作为生产要素的作用。 目前,该企业在北京、南京、西安、武汉等地均设有产研中心ÿ…...
Opencv入门五 (显示图片灰度值)
源码如下: #include <opencv2/opencv.hpp> int main(int argc, char** argv) { cv::Mat img_rgb, img_gry, img_cny; cv::namedWindow("Example Gray",cv::WINDOW_AUTOSIZE); cv::namedWindow("Example Canny", cv::WINDOW_…...
STM32F4 HAL流水灯Proteus仿真
源码下载:https://download.csdn.net/download/zlkk00/88654405...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
