从零玩转设计模式之建造者模式-jianzaozhemoshi

news2024/9/23 7:33:31
title: 从零玩转设计模式之建造者模式
date: 2022-12-08 18:15:30.898
updated: 2022-12-23 15:35:58.428
url: https://www.yby6.com/archives/jianzaozhemoshi
categories: 
- 设计模式
tags: 
- 设计模式
- 建造者模式

什么是建造者模式?

建造者模式是一种软件设计模式,它用于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通常用于创建复杂对象,它包含多个部分,每个部分可以有不同的组成方式。

需求

一个类计算机类Computer包括以下变量

  • cpu
  • ram
  • usbCount
  • keyboard
  • display

而其他3个是可选参数

  • usbCount
  • keyboard
  • display

两种常用的方式

折叠构造器模式

image-1670518413657

Javabean 直接定义

image-1670518422698

缺点

第1种

第一种主要是使用及阅读不方便。当调用一个类的构造函数时,
首先要决定使用哪一个,里面参数又很多,参数的类型也不一样,
这样很容易搞混

第2种

在构建过程中对象的状态容易发生变化,造成错误。
因为那个类中的属性是分步设置的,所以就容易出错。

特点

在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。

产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。
这类产品的创建无法用前面介绍的工厂模式描述,只有建造者模式可以很好地描述该类产品的创建。

建造者模式解决需求(代码实现)

第一步:创建目标类, 也就是我们的产品

/**
 * 产品 计算机
 *
 * @author yang shuai
 * @date 2022/12/4
 */
public class Computer {

    private final String cpu;// 必须
    private final String ram;// 必须
    private int usbCount;// 可选
    private String keyboard;// 可选
    private String display;// 可选

    public Computer(String cpu, String ram) {
        this.cpu = cpu;
        this.ram = ram;
    }

    public void setUsbCount(int usbCount) {
        this.usbCount = usbCount;
    }

    public void setKeyboard(String keyboard) {
        this.keyboard = keyboard;
    }

    public void setDisplay(String display) {
        this.display = display;
    }

    @Override
    public String toString() {
        return "Computer{" + "cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + ", usbCount=" + usbCount + ", keyboard='" + keyboard + '\'' + ", display='" + display + '\'' + '}';
    }


}

第二步:创建抽象构建者类

public abstract class ComputerBuilder {
    public abstract void buildCount(int usbCount);
    public abstract void buildKeyboard(String keyBoard);
    public abstract void buildDisplay(String display);

    public abstract Computer makeComputer();
}

第三步:创建具体建造者类

public class HWComputerBuilder extends ComputerBuilder{
    private Computer computer;
    public HWComputerBuilder(String cpu, String ram) {
        computer=new Computer(cpu,ram);
    }
    @Override
    public void buildCount(int usbCount) {
        computer.setUsbCount(usbCount);
    }

    @Override
    public void buildKeyboard(String keyBoard) {
        computer.setKeyboard(keyBoard);
    }

    @Override
    public void buildDisplay(String display) {
        computer.setDisplay(display);
    }

    @Override
    public Computer makeComputer() {
        return computer;
    }
}

第四步:创建指挥类

public class ComputerDirector {
    private ComputerBuilder builder;
    public void setBuilder(ComputerBuilder builder) {
        this.builder = builder;
    }

    public Computer makeComputer(int useCount,String display,String keyBoard){
       builder.buildCount(useCount);
       builder.buildDisplay(display);
       builder.buildKeyboard(keyBoard);
       return builder.makeComputer();
    }
}

定义

指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。

它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。即产品的组成部分是不变的,但每一部分是可以灵活选择的。

建造者模式与工厂模式的区别

工厂模式

  • 工厂模式注重于创建产品
  • 工厂模式创建出来的产品都是一个样子
  • 工厂模式的关注点是只要创建出对象就可以了

建造者模式

  • 建造者模式注重于方法的调用顺序
  • 建造者模式可以创建出复杂的产品,由各种复杂的部件组成
  • 建造者模式不仅要创建产品,,还要知道该产品是由哪些部件组成的

建造者模式包括四个角色:

  • Product(产品角色):一个具体的产品对象。
  • Builder(抽象建造者):创建一个Product对象的各个部件指定的接口/抽象类。
  • ConcreteBuilder(具体建造者):实现接口,构建和装配各个部件。
  • Director(指挥者):构建一个使用Builder接口的对象。
    • 它主要是用于创建一个复杂的对象。
    • 作用
      • 隔离了客户与对象的生产过程
      • 负责控制产品对象的生产过程。

建造者模式的优点有:

  • 它隔离了具体组建和装配方式,使得构建过程与具体实现分离。
  • 它支持构建复杂对象,并且可以控制复杂对象的构建顺序。
  • 它可以使得用户可以独立地改变一个对象的内部表示。
  • 它可以提供一种灵活的构建方式,在用户不确定最终的产品的具体细节时也可以创建对象。
  • 它可以有效地防止用户在构建过程中破坏产品的结构。

大白话:
封装性好,构建和表示分离。
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。

建造者模式的缺点有:

  • 产生多余的Builder对象
  • 产品内部发生变化,建造者都要修改,成本较大

建造者模式第二种写法

解决产生多余的Builder对象等

在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。

示例:

/**
 * 使用静态内部类构造数据
 *
 * @author yang shuai
 * @date 2022/12/9
 */
public class Computer {
    private final String cpu;//必须
    private final String ram;//必须
    private final int usbCount;//可选
    private final String keyboard;//可选
    private final String display;//可选

    @Override
    public String toString() {
        return "Computer{" + "cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + ", usbCount=" + usbCount + ", keyboard='" + keyboard + '\'' + ", display='" + display + '\'' + '}';
    }

    private Computer(Builder computerBuilder) {
        this.cpu = computerBuilder.cpu;
        this.ram = computerBuilder.ram;
        this.usbCount = computerBuilder.usbCount;
        this.keyboard = computerBuilder.keyboard;
        this.display = computerBuilder.display;
    }

    public static class Builder {
        private final String cpu;//必须
        private final String ram;//必须
        private int usbCount;//可选
        private String keyboard;//可选
        private String display;//可选

        public Builder(String cup, String ram) {
            this.cpu = cup;
            this.ram = ram;
        }

        public Builder buildUsbCount(int usbCount) {
            this.usbCount = usbCount;
            return this;
        }


        public Builder buildKeyboard(String keyboard) {
            this.keyboard = keyboard;
            return this;
        }

        public Builder buildDisplay(String display) {
            this.display = display;
            return this;
        }

        public Computer build() {
            return new Computer(this);
        }
    }
}

使用场景

如果一个对象有非常复杂的内部结构(很多属性)
想把复杂对象的创建和使用分离

总结

用来创建复杂的复合对象

源码分析

StringBuilder

  • JDK 的 StringBuilder 类中提供了 append() 方法,这就是一种链式创建对象的方法,开放构造步骤,最后调用 toString() 方法就可以获得一个完整的对象
    • image-1670519705111

SqlSessionFactoryBuilder

  • MyBatis 中 SqlSessionFactoryBuiler 类用到了建造者模式。且在 MyBatis 中 SqlSessionFactory是由 SqlSessionFactoryBuilder 产生的
    • image-1670519761214
    • image-1670519771112
    • XMLConfigBuilder 负责 Configuration 各个组件的创建和装配,整个装配的流程化过程如下:
    • image-1670519777949
    • XMLConfigBuilder 负责创建复杂对象 Configuration,其实就是一个具体建造者角色。
    • SqlSessionFactoryBuilder 只不过是做了一层封装去构建 SqlSessionFactory 实例,这就是建造者模式简化构建的过程。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

突发!OpenAI 重磅发布 ChatGPT iOS 客户端!无须手续费,直接开通Plus。

大家好,我是GG哥! 今天凌晨,OpenAI又重磅宣布推出ChatGPT的 iOS移动版本。也就是说,从今天开始iOS用户将可以在手机和iPad上免费下载和使用ChatGPT。 整体来说,iOS移动端的ChatGPT主打简洁流畅的风格,全力提…

Qt C++5.9开发指南

第1章 认识Qt 1.1 Qt简介 1、Qt是一套应用程序开发类库,但与MFC不同,Qt是跨平台开发类库。 2、跨平台意味着只需要编写一次程序,在不同平台上无需改动或只是需要少许改动后再编译,就可以形成不同平台上运行的版本。 1.2 Qt的获取与…

Python中的字典学习笔记

字典的格式:{"key":"value"} key表示数据的含义,value表示对应的数据的值字典是一种可变的数据类型,从python3.7开始,字典是有序的。 字典创建的方式 1、通过{},要使用key:value的格式&#xff0c…

​编程教室的文章是用什么库完成的?

入门教程、案例源码、学习资料、读者群 请访问: python666.cn 大家好,欢迎来到 Crossin的编程教室 ! Python 的一大特色是其丰富的模块,基本上只要你能想到的常见开发需求,都能找到别人已经实现的库直接使用&#xff0…

图的拓扑排序与关键路径

拓扑排序与关键路径是有向无环图上的应用。两种算法使用同一种动态规划的思想,因此关键路径的代码几乎和拓扑排序完全一样。 (一)拓扑排序 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一…

由浅入深Netty入门案例

目录 1 概述1.1 Netty 是什么?1.2 Netty 的作者1.3 Netty 的地位1.4 Netty 的优势 2 Hello World2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理2.5 提示 1 概述 1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework…

4.是人就能学会的Spring源码教程-IOC容器创建Bean对象

IOC容器创建Bean对象 简单了解Bean工厂 我们要关注一个接口BeanFactory,它是Spring IOC容器的根接口,也是容器的入口。 类的描述中已经清楚的说明了: 用于访问 Spring bean 容器的根接口。 这是 bean 容器的基本客户端视图;进一…

小牛电动疲软的销售趋势和不明朗的未来

来源:猛兽财经 作者:猛兽财经 小牛电动(NIU)的股价今年迄今为止已经下跌了6%。尽管该公司在蓬勃发展的电动汽车市场运营,但疫情的限制和欧洲的销售疲软导致小牛电动在欧市场的销量持续下降,猛兽财经认为,由于规模经济…

【LeetCode】528. 按权重随机选择

528. 按权重随机选择(中等) 思路 我们先把题目读懂。假设我们有数组 w[1,2,3,4], 那么这个数组的的和为 123 4 10 。我们得到 index (0,1,2,3) 的概率为 [1/10,2/10,3/10,4/10]。现在我们要返回(0,1,2,3) 中任意一个 index,但是我们要保证 p…

Docker安装MeiliSearch教程

MeiliSearch是一款开源的全文搜索引擎,它使用Rust编写,具有高效、快速、易用的特点。MeiliSearch支持多种语言,可以轻松地集成到任何应用程序中。它可以处理大量的文本数据,并能够快速地搜索和返回相关的结果。MeiliSearch还提供了…

[深度学习]大模型训练之框架篇-DeepSpeed

一 为什么需要Deepspeed 大模型(LLM)在训练时往往需要大量内存来存储中间激活、权重等参数,百亿模型甚至无法在单个 GPU上进行训练,使得模型训练在某些情况下非常低效和不可能。这就需要进行多卡,或者多节点分布式训练…

zabbix企业监控实战-1-zabbix部署

官网:https://www.zabbix.com 参考官网:https://www.zabbix.com/download?zabbix6.0&os_distributionrocky_linux&os_version8&componentsserver_frontend_agent&dbmysql&wsapache 1、环境准备 1> 修改主机名 [rootzabbix ~]# h…

Java --- redis7实现分布式锁

目录 一、锁的种类 二、分布式锁具备的条件与刚需 三、springbootredisngnix单机实现案例 四、Nginx配置负载均衡 4.1、修改nginx配置文件 4.2、执行启动命令 4.3、启动微服务程序测试 五、使用redis分布式锁 5.1、方法递归重试 5.2、自旋方式 5.3、添加key过期时间&#xff0…

业务实战记录4:多维表插入数据任务丢失处理与思考

本文目录 一、线程 bug二、解决方案2.1 加停顿2.2 单线程2.3 多 Token 三、一点花絮 很久没有写业务实战记录了,实际工作过程中其实遇到了挺多问题的,但是要通过 CSDN 记录下来,还是比较难的,因为场景和目标比较难说清楚&#xff…

【网络】HTTPHTTPS协议

文章目录 HTTP协议认识URLurlencode和urldecodeHTTP协议格式HTTP请求协议格式简单的小实验 HTTP响应协议格式关于封装解包分用 HTTP的方法关于GET和POST方法概念GET&POST对比(代码测试)测试POST和GET方法的区别 HTTP的状态码关于重定向的状态码临时重定向的代码演示: HTTP的…

【文献研究】轴辐式航线网络设计—Liner hub-and-spoke shipping network design

学习文献:轴辐式航线网络设计—Liner hub-and-spoke shipping network design 3. 模型建立 轴辐式航线网络设计 三级轴辐式网络:喂给港-二级枢纽港-一级枢纽港 主要考虑的限制条件:多种类型的集装箱船舶、转运时间、多种类型的集装箱 转运操…

Kangas:计算机视觉中的Pandas

介绍 在计算机视觉领域,Kangas是一种越来越受欢迎的工具,用于图像数据处理和分析。类似于Pandas如何改变数据分析人员处理表格数据的方式,Kangas对计算机视觉任务也起到了同样的作用。 Kangas是Comet ML开源的工具,用于探索、分析…

【Http协议①】认识http协议,学会使用fiddler抓包工具进行抓包.

前言: 大家好,我是良辰丫,今天我们一起来学习http协议,http协议是应用层的协议,应用层是最接近程序员的,那么,http协议到底是什么呢?我们往下看.💞💞 🧑个人主页:良辰针不戳 📖所属专栏:javaEE初阶 &#…

springboot+java养老院儿童福利院管理系统

安家儿童福利院管理系统包括儿童管理、申请领养管理、捐赠管理、楼栋管理、宿舍管理、分配信息管理、宿舍物品管理、报修管理、维修工管理、报修状态管理、留言管理、系统管理。通过对系统的实现得出安家儿童福利院管理系统具有安全稳定、操作简单、功能强大等特点,…

MySQL8.0卸载、安装和使用(二)

MySQL数据库的安装 注意: 必须用系统管理员身份运行mysql安装程序。安装目录切记不要用中文。 步骤一:双击mysql8的安装向导 步骤二:分为首次安装和再安装 1、首次安装 (1)如果是首次安装mysql系列的产品&#xff…