【设计模式-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 {
    @Override
    public void buildSignIn() {
        person.setSignIn("学生已签到");
    }

    @Override
    public void buildProfile() {
        person.setProfile("学生信息已录入");
    }

    @Override
    public void buildIdCard() {
        person.setIdCard("学生证已办理");
    }
}

(Teacher,教师类,继承人员建造者,重写教师入学相关方法)

/**
 * 教师入学
 */
public class Teacher extends PersonBuilder {
    @Override
    public void buildSignIn() {
        person.setSignIn("老师已签到");
    }

    @Override
    public void buildProfile() {
        person.setProfile("老师个人信息已录入");
    }

    @Override
    public void buildIdCard() {
        person.setIdCard("老师身份证已办理");
    }
}

(Employee,职工类,继承人员建造者,重写职工入学相关方法)

/**
 * 职工入学
 */
public class Employee extends PersonBuilder {
    @Override
    public void buildSignIn() {
        person.setSignIn("员工已签到");
    }

    @Override
    public void buildProfile() {
        person.setProfile("员工个人信息已录入");
    }

    @Override
    public 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 {
    @Override
    public void buildSignIn() {
        person.setSignIn("老师已签到");
    }

    @Override
    public void buildProfile() {
        person.setProfile("老师个人信息已录入");
    }

    @Override
    public void buildIdCard() {
        person.setIdCard("老师身份证已办理");
    }

    @Override
    public 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类。

小结

建造者模式,通过定义一个抽象建造者类,封装了对象创建的细节,另外通过“钩子”方法,可细化对象创建过程,降低了系统复杂度,维护了系统的灵活性和扩展性。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在Windows上使用 Python

本文档旨在概述在 Microsoft Windows 上使用 Python 时应了解的特定于 Windows 的行为。 与大多数UNIX系统和服务不同,Windows系统没有预安装Python。多年来CPython 团队已经编译了每一个 发行版 的Windows安装程序(MSI 包),已便…

世微 AP5101C高压线性LED恒流驱动芯片 6-100V 2A LED灯电源驱动

产品描述 AP5101C 是一款高压线性 LED 恒流 芯片 , 简单 、 内置功率管 , 适用于 6- 100V 输入的高精度降压 LED 恒流驱动 芯片。电流2.0A。 AP5101C 可实现内置MOS 做 2.0A, 外置MOS 可做 3.0A 的。 AP5101C 内置温度保护功能 ,温度保 护点…

CSS 网页制作-学成在线

1、 准备工作 1.1 项目目录 网站根目录是指存放网站的第一层文件夹,内部包含当前网站的所有素材,包含HTML、CSS、图片、JavaScript等等。 1.2 版心效果 可以发现都是呈现版心居中的效果,但是每次都写一次太麻烦了,可以把版心居中…

java设计模式学习之【责任链模式】

文章目录 引言责任链模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用日志示例代码地址 引言 在现实生活中,常常会遇到这样的场景:一个请求或命令需要经过多个层级的处理。例如,一个行政审批流程可能需要通过多个部门的审…

【视觉实践】使用Mediapipe进行目标检测:杯子检测和椅子检测实践

目录 1 Mediapipe 2 Solutions 3 安装mediapipe 4 实践 1 Mediapipe Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning,ML)方案。MediaPipe是一个用于构建机器学习管道</

成为一名FPGA工程师:面试题与经验分享

在现代科技领域&#xff0c;随着数字电子技术的迅猛发展&#xff0c;FPGA&#xff08;可编程逻辑器件&#xff09;工程师成为了备受瞩目的职业之一。FPGA工程师不仅需要掌握硬件设计的基本原理&#xff0c;还需要具备良好的编程能力和解决问题的实践经验。面对如此竞争激烈的行…

DRF从入门到精通二(Request源码分析、DRF之序列化、反序列化、反序列化校验、序列化器常用字段及参数、source、定制字段、保存数据)

文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结&#xff1a; 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验序…

老师的责任和义务

作为一名老师&#xff0c;我们的责任和义务是重大的。在教育领域&#xff0c;我们扮演着至关重要的角色&#xff0c;肩负着培养下一代人才的重任。下面&#xff0c;我将以知乎的口吻&#xff0c;从几个方面谈谈老师的责任和义务。 确保学生获得高质量的教育。这包括制定合理的教…

【XR806开发板试用】通过http请求从心知天气网获取天气预报信息

1. 开发环境搭建 本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中&#xff0c;关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统&#xff08;WSL&#xff09; (1) 在WSL的Ubuntu20.04下安装必要的工具的. 安装git: sudo apt-get install git …

在线客服系统推荐:优质选择助您提升客户服务体验

大部分企业依靠在线客服系统和客户达成联系&#xff0c;他为客户和企业之间建立了有效的沟通桥梁。市场上这么多的在线客服系统哪个好呢&#xff1f; 1、明确自己的需求。 这一点是最重要的&#xff0c;要先明确公司使用客服系统是想做售前咨询还是售后服务。不同的需求相对应…

[笔记]ByteBuffer垃圾回收

参考&#xff1a;https://blog.csdn.net/lom9357bye/article/details/133702169 public static void main(String[] args) throws Throwable {List<Object> list new ArrayList<>();Thread thread new Thread(() -> {ByteBuffer byteBuffer ByteBuffer.alloc…

自动评估作业,支持订正最终得分、查看关联代码|ModelWhale 版本更新

冬至时节&#xff0c;2023 已进入尾声&#xff0c;ModelWhale 于今日迎来新一轮的版本更新&#xff0c;与大家一起静候新年的到来。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; 自动评估作业 新增 提交代码&#xff08;团队版✓ &#xff09;新增…

【Netty】编解码器

目录 Java的编解码Netty编解码器概念解码器(Decoder)编码器(Encoder)编码解码器Codec Java的编解码 编码&#xff08;Encode&#xff09;称为序列化&#xff0c; 它将对象序列化为字节数组&#xff0c;用于网络传输、数据持久化或者其它用途。 解码&#xff08;Decode&#x…

本地无法连接注册中心eureka,如何进行feign调用,并快速启动本地调试?

前言 今年进入了个新公司&#xff0c;接手代码时遇到了比较蛋疼的事情&#xff0c;本地代码调试遇到了层层阻碍&#xff0c;无法一键简单启动就算了&#xff0c;我就忍了&#xff0c;一番操作终于启动起了了&#xff0c;启动又慢&#xff0c;启动了2~3分钟&#xff0c;后面调本…

【音视频】remb twcc原理

目录 twcc简介 WebRTC REMB 参考文档 twcc简介 TWCC全称是Transport wide Congestion Control&#xff0c;是webrtc的最新的拥塞控制算法。其原理是在接收端保存数据包状态&#xff0c;然后构造RTCP包反馈给发送端&#xff0c;反馈信息包括包到达时间、丢包状态等&#xff…

养老院自助饮水机(字符设备驱动)

目录 1、项目背景 2、驱动程序 2.1 三层架构 2.2 驱动三要素 2.3 字符设备驱动 2.3.1 驱动模块 2.3.2 应用层 3、设计实现 3.1 项目设计 3.2 项目实现 3.2.1 驱动模块代码 3.2.2 用户层代码 4、功能特性 5、技术分析 6. 总结与未来展望 1、项目背景 养老院的老人…

社交网络分析(汇总)

这里写自定义目录标题 写在最前面社交网络分析系列文章汇总目录 提纲问题一、社交网络相关定义和概念提纲问题1. 社交网络、社交网络分析&#xff1b;2. 六度分隔理论、贝肯数、顿巴数&#xff1b;3. 网络中的数学方法&#xff1a;马尔科夫过程和马尔科夫链、平均场理论、自组织…

仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口

源码介绍 最新仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口&#xff0c; 全新开发悬赏任务系统&#xff0c;功能齐全&#xff0c;包含接任务&#xff0c;发布任务&#xff0c; 店铺关注&#xff0c;置顶推荐&#xff0c;排行榜&#xff0c;红包大厅&#xff0c;红包抽奖…

Android Studio如何实现 成语接龙游戏(简单易上手)

该项目是一个基于Android Studio和Java语言编写的成语接龙游戏App。成语接龙是一种经典的中文文字游戏&#xff0c;旨在测试玩家的词汇量和思维敏捷性。该成语接龙游戏App旨在提供一种有趣、挑战性和教育性的游戏体验。玩家可以通过游戏提高自己的中文词汇量和思维敏捷性&#…

Text Intelligence - TextIn.com AI时代下的智能文档识别、处理、转换

本指南将介绍Text Intelligence&#xff0c;AI时代下的智能文档技术平台 Textin.com 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认…