设计模式Java实现-建造者模式

楔子

小七在2019年的时候,就想写一个关于设计模式的专栏,但是最终却半途而废了。粗略一想,如果做完一件事要100分钟,小七用3分钟热情做的事,最少也能完成10件事情了。所以这一次,一定要把他做完,fighting!

需求背景

以以前小七做的一个政务系统为例,为了符合国标,数据库表需要设计很多字段,大概有100多个。每次new这个实体的时候,都会调用大量的set方法,关键是这100个字段基本不会变,但是他们的组合却经常变,弄得开发的小伙伴们苦不堪言,于是前辈们就重载了很多的构造方法,结果构造方法也爆炸了,导致新来的后浪们差点直接被拍死在了沙滩上。

为了简化代码,咱们这一次就定义一个Student类,里面只包含name和age。

分析设计

因为这个对象的属性很多,且组合方式很自由,如果使用经典的new-set方式,代码大概如下:

BigObject bigObject = new BigObject();
bigObject.setO1("");
bigObject.setO2("");
bigObject.setO3("");
bigObject.setO4("");
bigObject.setO5("");
bigObject.setO6("");
bigObject.setO7("");
bigObject.setO8("");
bigObject.setO9("");
bigObject.setO10("");
...
bigObject.setO100("");   

看起来并不直观。

如果每一个组合就重载一个构造方法,也会产生很多构造方法,并且语义不明,新来的小伙伴会一脸懵逼。

但是如果我们能够抽象一下产品的构建过程,具体建造者类继承自抽象建造者类,实现具体的构建逻辑。指挥者类负责调用具体建造者类的构建方法,完成产品的构建。这样就可以降低客户端代码的复杂度,提高代码的可维护性。

定义类名
产品类Student
抽象建造者类StudentBuilder
具体建造者类StudentActualBuilder
指挥者类Commander

标准建造者模式

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

file

模块名称

builder.demo01

模块地址

https://gitee.com/diqirenge/design-pattern/tree/master/src/main/java/com/run2code/design/creational/builder/demo01

模块描述

经典模式代码示例

代码实现

1、定义产品类

/*** 定义产品类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Student {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

2、定义抽象建造者类

/*** 定义抽象建造者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public abstract class StudentBuilder {public abstract void buildName(String name);public abstract void buildAge(int age);public abstract Student makeStudent();
}

3、定义具体建造者类

/*** 定义具体建造者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class StudentActualBuilder extends StudentBuilder {/*** 这里使用组合,将 student 组合到实现类中*/private Student student = new Student();@Overridepublic void buildName(String name) {student.setName(name);}@Overridepublic void buildAge(int age) {student.setAge(age);}@Overridepublic Student makeStudent() {return student;}
}

4、定义指挥者类

/*** 定义指挥者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Commander {/*** 注入StudentBuilder*/private StudentBuilder studentBuilder;public void setStudentBuilder(StudentBuilder studentBuilder) {this.studentBuilder = studentBuilder;}public Student makeStudent(String name, int age) {this.studentBuilder.buildAge(age);this.studentBuilder.buildName(name);return this.studentBuilder.makeStudent();}
}

5、测试

public class BuilderStudentBuilderTest {@Testpublic void testBuild_01() {System.out.println("==========标准建造者模式开始==========");StudentActualBuilder studentActualBuilder = new StudentActualBuilder();Commander commander = new Commander();commander.setStudentBuilder(studentActualBuilder);// 客户端使用指挥者类创建产品对象,这样可以降低客户端代码的复杂度,提高代码的可维护性。Student student = commander.makeStudent("第七人格", 18);System.out.println(student);System.out.println("==========标准建造者模式结束==========");}
}

6、测试结果

==========标准建造者模式开始==========

Student{name='第七人格', age=18}

==========标准建造者模式结束==========

实现要点

  1. 定义产品类:产品类是最终要构建的对象,包含多个属性和方法。

  2. 定义抽象建造者类:抽象建造者类定义了产品的构建过程,包括各个部分的构建方法和返回最终产品的方法。

  3. 定义具体建造者类:具体建造者类继承自抽象建造者类,实现具体的构建逻辑。

  4. 定义指挥者类:指挥者类负责调用具体建造者类的构建方法,完成产品的构建。

用过StringBuilder的我们知道,StringBuilder有个append方法,我们学着StringBuilder将上面的代码,改为链式调用。

链式调用模式

URL图

file

模块名称

builder.demo02

模块地址

https://gitee.com/diqirenge/design-pattern/tree/master/src/main/java/com/run2code/design/creational/builder/demo02

模块描述

建造者-链式调用

代码实现

/*** 链式调用建造者示例* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Student02Builder {/*** 姓名*/private String name;/*** 年龄*/private int age;/*** 学生类的构造函数** @param name 的名字* @param age  年龄*/Student02Builder(String name, int age) {this.name = name;this.age = age;}/*** 构建器(本质上就是指挥者Commander)** @return {@link StudentBuilder}*/public static Student02Builder.StudentBuilder builder() {// 构造一个StudentBuilder对象return new Student02Builder.StudentBuilder();}/*** 学生构建器(相当于StudentBuilder及其实现类StudentActualBuilder)** @author 第七人格* @date 2020/12/02*/public static class StudentBuilder {private String name;private int age;public StudentBuilder() {}public Student02Builder.StudentBuilder name(String name) {this.name = name;// 返回自身(StudentBuilder),以便链式调用return this;}public Student02Builder.StudentBuilder age(int age) {this.age = age;// 返回自身(StudentBuilder),以便链式调用return this;}/*** 构建** @return {@link Student02Builder}*/public Student02Builder build() {// 构造一个Student对象,其中的属性直接从外部传入return new Student02Builder(this.name, this.age);}@Overridepublic String toString() {return "Student.StudentBuilder(name=" + this.name + ", age=" + this.age + ")";}}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试

@Test
public void testBuild_02() {System.out.println("==========工作中常用-建造者模式开始==========");System.out.println(Student02Builder.builder().age(18).name("第七人格").build());System.out.println("==========工作中常用-建造者模式开始==========");
}

测试结果

==========链式调用-建造者模式开始==========

Student{name='第七人格', age=18}

==========链式调用-建造者模式开始==========

实现要点

1、使用静态方法替换指挥者Commander

public static Student02Builder.StudentBuilder builder() {// 构造一个StudentBuilder对象return new Student02Builder.StudentBuilder();
}

2、使用内部类替换StudentBuilder及StudentActualBuilder

3、内部类中设置属性的时候,返回自身,以便链式调用

面对对象面对君,不负代码不负卿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320586.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端】HTML实现个人简历信息填写页面

文章目录 前言一、综合案例:个人简历信息填写页面 前言 这篇博客仅仅是对HTML的基本结构进行了一些说明,关于HTML的更多讲解以及CSS、Javascript部分的讲解可以关注一下下面的专栏,会持续更新的。 链接: Web前端学习专栏 下面我对…

【毕业设计】基于SSM的运动用品商城的设计与实现

1.项目介绍 在这个日益数字化和信息化的时代,随着人们购物习惯的转变,传统的实体商店已经无法满足人们日益增长的在线购物需求。因此,基于SSM(Spring Spring MVC MyBatis)框架的运动用品商城项目应运而生&#xff0…

LearnOpenGL(七)之摄像机

一、摄像机/观察空间 当我们讨论摄像机/观察空间(Camera/View Space)的时候,是在讨论以摄像机(人)的视角作为场景原点时场景中所有的顶点坐标:观察矩阵把所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。要定义一个摄像机…

探索Kimi模型AI:革新人工智能的未来

探索Kimi模型AI:革新人工智能的未来 人工智能(AI)技术的发展已经取得了巨大的进步,为我们的生活带来了许多便利和创新。在这个充满活力和竞争的领域中,Kimi模型AI以其独特的设计和功能吸引了人们的注意。本文将深入探…

final关键词

基本介绍 final 中文意思是:最后的,最终的final可以修饰 类、属性、方法和局部变量何时会用到final: 1,当不希望类被继承时,可以用final修饰 2,当不希望父类的某个方法被子类覆盖/重写(overrid…

矩阵式键盘的控制

键盘扫描是最 为常用的工作方式,扫描方式又可分为程序程扫描、定时扫描和中断扫描。程序扫描是指在 特定的程序位置段上安排键盘扫描程序读取键盘状态。定时扫描是指利用单片机内部或扩展 的定时器产生定时中断,在中断中进行键盘扫描的工作方式。中断扫描…

全国产业园运营排名前十!树莓集团助推载体运营高质量发展

树莓集团,作为数字产业生态链的杰出建设者,以及在全国产业园运营中名列前茅的领航者,其独特的集团核心文化——高效、友善、敢为,成为了推动其不断前行的强大动力。树莓集团深谙在数字化时代,政、产、企、校四个板块之…

硬件设计 之 压敏电阻简单介绍

1. 什么是压敏电阻(Varistor Voltage): 压敏电阻(Varistor)是一种特殊类型的电阻器件,具有非线性电阻特性。它的主要作用是保护电子电路免受过电压或过电流的损害。 测定电流为1mA,此时TNR端子…

纯血鸿蒙APP实战开发——页面间共享组件实例的案例

介绍 本示例提供组件实例在页面间共享的解决方案:通过Stack容器,下层放地图组件,上层放Navigation组件来管理页面,页面可以共享下层的地图组件,页面中需要显示地图的区域设置为透明,并参考触摸交互控制&am…

HTML_CSS学习:定位

一、相对定位 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>相对定位</title><style>.outer{width: 500px;background-color: #999ff0;border: 1px solid #000;p…

BEV下统一的多传感器融合框架 - FUTR3D

BEV下统一的多传感器融合框架 - FUTR3D 引言 在自动驾驶汽车或者移动机器人上&#xff0c;通常会配备许多种传感器&#xff0c;比如&#xff1a;光学相机、激光雷达、毫米波雷达等。由于不同传感器的数据形式不同&#xff0c;如RGB图像&#xff0c;点云等&#xff0c;不同模态…

【Docker学习】docker start深入研究

docker start也是很简单的命令。但因为有了几个选项&#xff0c;又变得复杂&#xff0c;而且... 命令&#xff1a; docker container start 描述&#xff1a; 启动一个或多个已停止的容器。 用法&#xff1a; docker container start [OPTIONS] CONTAINER [CONTAINER...] 别名&…

标准IO学习

思维导图&#xff1a; 有如下结构体 struct Student{ char name[16]; int age; double math_score; double chinese_score; double english_score; double physics_score; double chemistry_score; double bio_score; }; 申请该结构体数组&#xff0c;容量为5&#xff0c;初始…

Android手写自己的路由SDK

实现自己的路由框架 ​ 在较大型的Android app中常会用到组件化技术&#xff0c;针对不同的业务/基础功能对模块进行划分&#xff0c;从上到下为壳工程、业务模块、基础模块。其中业务模块依赖基础模块&#xff0c;壳工程依赖业务模块。同级的横向模块&#xff08;比如多个业务…

小微公司可用的开源ERP系统

项目介绍 华夏ERP是基于SpringBoot框架和SaaS模式的企业资源规划&#xff08;ERP&#xff09;软件&#xff0c;旨在为中小企业提供开源且易用的ERP解决方案。它专注于提供进销存、财务和生产功能&#xff0c;涵盖了零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询…

【SpringMVC 】什么是SpringMVC(二)?如何整合ssm框架以及使用mybatisPlus?

文章目录 SpringMVC第三章1、ssm整合1、基本步骤1-3步4-5步6步7步8-12步13步14-15步2、添加数据3、删除数据4、配置事务5、修改数据2、pageHelpe分页1、基本步骤第四章1、mybatisPlus1、基本步骤1-45-7892、基本方法的使用查询2、新ssm项目1、基本步骤1-5678-910-111213-15Spri…

[C++][数据结构]红黑树的介绍和模拟实现

前言 之前我们简单学习了一下搜索树和平衡搜索树&#xff0c;今天我们来学习一下红黑树 简介 概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着…

数据结构学习/复习8--树与二叉树的概念与基本性质练习

一、树 1.概念 2.树的表示 二、二叉树 1.二叉树的概念 2.与性质相关的题

有什么方便的教学口语软件?6个软件教你快速练习口语

有什么方便的教学口语软件&#xff1f;6个软件教你快速练习口语 以下是六个方便实用的教学口语软件&#xff0c;它们可以帮助您快速练习口语&#xff1a; AI外语陪练: 这是一款知名的语言学习软件&#xff0c;提供多种语言的口语练习课程。它采用沉浸式的学习方法&#xff0…

【iOS】NSOperation、NSOperationQueue

文章目录 前言一、NSOperation、NSOperationQueue 简介二、NSOperation、NSOperationQueue 操作和操作队列三、NSOperation四、NSOperationQueue五、NSOperationQueue 控制串行执行、并发执行六、 NSOperation 操作依赖七、NSOperation 优先级八、NSOperation、NSOperationQueu…