当前位置: 首页 > news >正文

【设计模式-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&#xff08;兴趣点&#xff09; 代码实现 index.wxml <!-- index.wxml --> <view class"container&…...

Vue如何请求接口——axios请求

1、安装axios 在cmd或powershell打开文件后&#xff0c;输入下面的命令 npm install axios 可在项目框架中的package.json中查看是否&#xff1a; 二、引用axios import axios from axios 在需要使用的页面中引用 三、get方式使用 get请求使用params传参,本文只列举常用参数…...

【数据结构一】初始Java集合框架(前置知识)

Java中的数据结构 Java语言在设计之初有一个非常重要的理念便是&#xff1a;write once&#xff0c;run anywhere&#xff01;所以Java中的数据结构是已经被设计者封装好的了&#xff0c;我们只需要实例化出想使用的对象&#xff0c;便可以操作相应的数据结构了&#xff0c;本篇…...

直接将第三方数据插入到 Redis 中

Redis 是一个内存数据库&#xff0c;可以用于缓存和持久化数据。虽然常见的使用场景是将数据从关系型数据库&#xff08;如MySQL&#xff09;同步到 Redis 中进行缓存&#xff0c;但也可以直接将第三方数据插入到 Redis 中。 你可以通过编程语言的 Redis 客户端库&#xff08;…...

【重点】【DP】322.零钱兑换

题目 法1&#xff1a;动态规划 // 时间复杂度&#xff1a;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 表格实现拖拽排序的功能&#xff0c;可以借助第三方插件Sortablejs来实现。 引入sortablejs npm install sortablejs --save组件中使用 import Sortable from sortablejs;<el-table ref"el-table":data"listData" row-key"id" …...

2. 结构型模式 - 桥接模式

亦称&#xff1a; Bridge 意图 桥接模式是一种结构型设计模式&#xff0c; 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构&#xff0c; 从而能在开发时分别使用 问题 抽象&#xff1f; 实现&#xff1f; 听上去挺吓人&#xff1f; 让我们慢慢来&#x…...

最小二乘法简介

最小二乘法简介 1、背景描述2、最小二乘法2.1、最小二乘准则2.2、最小二乘法 3、最小二乘法与线性回归3.1、最小二乘法与线性回归3.2、最小二乘法与最大似然估计 4、正态分布&#xff08;高斯分布&#xff09; 1、背景描述 在工程应用中&#xff0c;我们通常会用一组观测数据去…...

mathtype公式章节编号

1. word每章标题后插入章节符 如果插入后显示章节符&#xff0c;需要进行隐藏 开始->样式->MTEquationSection->修改样式->字体&#xff0c;勾选隐藏 2. 设置mathtype公式编号格式 插入编号->格式化->设置格式...

医学实验室检验科LIS信息系统源码

实验室信息管理是专为医院检验科设计的一套实验室信息管理系统&#xff0c;能将实验仪器与计算机组成网络&#xff0c;使病人样品登录、实验数据存取、报告审核、打印分发&#xff0c;实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。 实验室管理系统功能介…...

无需改动现有网络,企业高速远程访问内网Linux服务器

某企业为数据治理工具盒厂商&#xff0c;帮助客户摆脱数据问题困扰、轻松使用数据&#xff0c;使得客户可以把更多精力投入至数据应用及业务赋能&#xff0c;让数据充分发挥其作为生产要素的作用。 目前&#xff0c;该企业在北京、南京、西安、武汉等地均设有产研中心&#xff…...

Opencv入门五 (显示图片灰度值)

源码如下&#xff1a; #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仿真

源码下载&#xff1a;https://download.csdn.net/download/zlkk00/88654405...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁

赛门铁克威胁猎手团队最新报告披露&#xff0c;数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据&#xff0c;严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能&#xff0c;但SEMR…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...