设计模式-建造者模式在Java中使用示例

news2024/10/7 10:12:56

场景

建造者模式

复杂对象的组装与创建

没有人买车会只买一个轮胎或者方向盘,大家买的都是一辆包含轮胎、方向盘和发动机等多个部件的完整汽车。

如何将这些部件组装成一辆完整的汽车并返回给用户,这是建造者模式需要解决的问题。

建造者模式又称为生成器模式,它是一种较为复杂、使用频率也相对较低的创建型模式。

建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品。

建造者模式是较为复杂的创建型模式,它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离,

客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。

它关注如何一步一步创建一个的复杂对象,不同的具体建造者定义了不同的创建过程,

且具体建造者相互独立,增加新的建造者非常方便,无须修改已有代码,系统具有较好的扩展性。

建造者模式举例

以角色扮演类游戏为例,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。

不同类型的游戏角色,其性别、脸型、服装等外部特性都有所差异。

开发一个小工具来创建游戏角色,可以创建不同类型的角色并可以灵活增加新的角色。

游戏角色是一个复杂对象,它包含性别、脸型等多个组成部分,不同的游戏角色其组成部分有所差异。

无论是何种造型的游戏角色,它的创建步骤都大同小异,都需要逐步创建其组成部分,

再将各组成部分装配成一个完整的游戏角色。如何一步步创建一个包含多个组成部分的复杂对象,

建造者模式为解决此类问题而诞生。

建造者模式结构图与角色

 

建造者模式中包含如下角色

Builder(抽象建造者):
它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,
一类方法是buildPartX(),它们用于创建复杂对象的各个部件;
另一类方法是getResult(),它们用于返回复杂对象。
Builder既可以是抽象类,也可以是接口。

ConcreteBuilder(具体建造者):
它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,
也可以提供一个方法返回创建好的复杂产品对象。
在ConcreteBuilder中实现了buildPartX()方法,通过调用Product的setPartX()方法可以给产品对象的成员属性设值。
不同的具体建造者在实现buildPartX()方法时将有所区别,如setPartX()方法的参数可能不一样,
在有些具体建造者类中某些setPartX()方法无须实现(提供一个空实现)。
而这些对于客户端来说都无须关心,客户端只需知道具体建造者类型即可。

Product(产品角色):
它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
复杂对象是指那些包含多个成员属性的对象,这些成员属性也称为部件或零件,如汽车包括方向盘、发动机、轮胎等部件,
电子邮件包括发件人、收件人、主题、内容、附件等部件

Director(指挥者):
指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,
可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。
客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),
然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。
该类主要有两个作用:
一方面它隔离了客户与创建过程;
另一方面它控制产品的创建过程,包括某个buildPartX()方法是否被调用以及多个buildPartX()方法调用的先后次序等。
指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。
在实际生活中也存在类似指挥者一样的角色,如一个客户去购买电脑,电脑销售人员相当于指挥者,只要客户确定电脑的类型,
电脑销售人员可以通知电脑组装人员给客户组装一台电脑。

建造者模式与工厂模式有何区别?

建造者模式与抽象工厂模式有点相似,但是建造者模式返回一个完整的复杂产品,而抽象工厂模式返回一系列相关的产品;
在抽象工厂模式中,客户端通过选择具体工厂来生成所需对象,而在建造者模式中,
客户端通过指定具体建造者类型并指导Director类如何去生成对象,侧重于一步步构造一个复杂对象,然后将结果返回。
如果将抽象工厂模式看成一个汽车配件生产厂,生成不同类型的汽车配件,那么建造者模式就是一个汽车组装厂,通过对配件进行组装返回一辆完整的汽车。

设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例:

设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例_java工厂模式应用场景举例_霸道流氓气质的博客-CSDN博客

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主

实现

下面使用建造者模式实现上面角色设计的流程

1、新建Actor充当复杂产品,这里使用lombok省略get和set方法。

import lombok.Data;

/**
 * 充当复杂产品
 */
@Data
public class Actor {
    //角色类型
    private String type;
    //性别
    private String sex;
    //脸型
    private String face;
    //服装
    private String costume;
}

2、新建抽象构造者ActorBuilder,并新增方法,返回一个完整的游戏角色对象

/**
 * 抽象构造者
 */
public abstract class ActorBuilder {

    protected Actor actor = new Actor();

    public abstract void buildType();
    public abstract void buildSex();
    public abstract void buildFace();
    public abstract void buildContume();

    //工厂方法,返回一个完整的游戏角色对象
    public Actor createActor(){
        return actor;
    }
}

3、具体建造者一共有三种角色:英雄、天使、恶魔

英雄角色构造器实现

/**
 * 英雄角色建造器:具体建造者
 */
public class HeroBuilder extends ActorBuilder {

    @Override
    public void buildType() {
        actor.setType("英雄");
    }

    @Override
    public void buildSex() {
        actor.setSex("男");
    }

    @Override
    public void buildFace() {
        actor.setFace("帅气");
    }

    @Override
    public void buildContume() {
        actor.setCostume("盔甲");
    }
}

天使角色构造器实现

/**
 * 天使角色建造器:具体建造者
 */
public class AngelBuilder extends ActorBuilder{
    @Override
    public void buildType() {
        actor.setType("天使");
    }

    @Override
    public void buildSex() {
        actor.setSex("女");
    }

    @Override
    public void buildFace() {
        actor.setFace("漂亮");
    }

    @Override
    public void buildContume() {
        actor.setCostume("翅膀");
    }
}

恶魔角色构造器实现

/**
 * 恶魔角色建造器:具体建造者
 */
public class DeviBuilder extends ActorBuilder
{
    @Override
    public void buildType() {
        actor.setType("恶魔");
    }

    @Override
    public void buildSex() {
        actor.setSex("男");
    }

    @Override
    public void buildFace() {
        actor.setFace("吓人");
    }

    @Override
    public void buildContume() {
        actor.setCostume("皮衣");
    }
}

4、新建指挥者-角色创建控制器

/**
 * 角色创建控制器:指挥者
 */
public class ActorController{

    //逐步构建复杂产品对象
    public Actor construct(ActorBuilder builder){
        Actor actor;
        builder.buildType();
        builder.buildSex();
        builder.buildFace();
        builder.buildContume();
        actor = builder.createActor();
        return actor;
    }
}

5、客户端调用方式如下

        //针对抽象构造者编程
        ActorBuilder actorBuilder;
        //通过配置文件或其他方式获取具体的建造者
        actorBuilder = new HeroBuilder();
        ActorController actorController = new ActorController();
        Actor actor;
        actor = actorController.construct(actorBuilder);
        System.out.println(actor);

6、总结

在建造者模式中,客户端只需实例化指挥者类,指挥者类针对抽象建造者编程,客户端根据需要传入
具体的建造者类型,指挥者将指导具体建造者一步一步构造一个完整的产品(逐步调用具体建造者的
buildX()方法),相同的构造过程可以创建完全不同的产品。在游戏角色实例中,如果需要更换角
色,只需要修改配置文件,更换具体角色建造者类即可;如果需要增加新角色,可以增加一个新的具
体角色建造者类作为抽象角色建造者的子类,再修改配置文件即可,原有代码无须修改,完全符合“开
闭原则”。

建造者模式的主要优点如下:
(1) 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使
得相同的创建过程可以创建不同的产品对象。
(2) 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者
或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽
象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合“开闭原则”
(3) 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过
程更加清晰,也更方便使用程序来控制创建过程

建造者模式的主要缺点如下:
(1) 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很
大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。
(2) 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变
得很庞大,增加系统的理解难度和运行成本。

适用场景
在以下情况下可以考虑使用建造者模式:
(1) 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
(2) 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
(3) 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装
在指挥者类中,而不在建造者类和客户类中。
(4) 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

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

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

相关文章

复选框,购物车功能,单选,全选

<template><view class"index"><u-navbar title"购物车" :is-back"false" :border-bottom"false" title-color"#333":background"{background:#fff}"><view class"page_navbar_warp&qu…

探究ThreadLocal和ThreadPoolExecutor中的内存泄露风险与防范策略

探究ThreadLocal和ThreadPoolExecutor中的内存泄露风险与防范策略 本文将探讨ThreadLocal和ThreadPoolExecutor中可能存在的内存泄露问题&#xff0c;并提出相应的防范策略。 ThreadPoolExecutor的内存泄露问题 ThreadPoolExecutor是一个线程池类&#xff0c;它可以管理和复…

【PHP面试题39】linux下面chmod和chown使用详解

文章目录 一、前言二、什么是 chmod 命令&#xff1f;2.1 使用方法&#xff1a;2.2 数值表示法&#xff1a;2.3 符号表示法&#xff1a; 三、什么是 chown 命令&#xff1f;3.1 使用方法&#xff1a;3.2 更改所有者和用户组&#xff1a; 四、使用示例4.1 使用 chmod 命令修改权…

媒体邀约:企业新品发布会如何邀约记者到现场采访报道?

媒介易是国内领先的全媒体广告营销平台&#xff0c;专注全媒体营销平台创新服务。我们有超过近11年的实战经验&#xff0c;我们拥有丰富的媒体记者资源&#xff0c;关于邀约记者到现场采访&#xff0c;我们会采取以下步骤&#xff1a; 1、提前策划&#xff1a;在发布会前至少…

MATLAB 基于NDT的点云配准实验(不同参数效果) (25)

MATLAB 基于NDT的点云配准实验(不同参数效果) (25) 一、算法简介二、具体使用1.代码(注释详细)2.结果(不同参数 与ICP比较)一、算法简介 NDT点云配准与ICP一样,都是经典的点云配准算法,这里使用MATLAB进行ndt点云配准,对配准结果进行显示,并尝试不同参数,得到较好…

单元测试用例到底该如何设计?

目录 前言 使用参数方法创建测试用例 使用执行路径方法创建测试用例 总结 前言 最近一些大公司在进行去测试化的操作&#xff0c;这一切的根源大概可以从几年前微软一刀切砍掉所有内部正式的测试人员开始说起&#xff0c;当时微软内部的测试工程师有一部分转职成了开发工程…

STM32 Proteus仿真红外检测PWM调速温控风扇-0073

STM32 Proteus仿真红外检测PWM调速温控风扇-0073 Proteus仿真小实验&#xff1a; STM32 Proteus仿真红外检测PWM调速温控风扇-0073 功能&#xff1a; 硬件组成&#xff1a;STM32F103C6单片机 LCD1602显示器DS18B20温度传感器人检测 按下说明有人L298驱动电机模拟风扇 1.按键…

PWM呼吸灯设计

呼吸灯&#xff1a; 呼吸灯是一种特殊的灯光效果&#xff0c;它可以模拟呼吸的效果&#xff0c;即灯光逐渐由暗变亮再由亮变暗&#xff0c;循环往复。这种效果给人一种柔和、舒缓的感觉&#xff0c;常被应用在装饰、照明和显示等领域。 PWM呼吸灯设计&#xff1a; 在数字电路设…

Windows搭建Nginx实现RTMP转为HLS流

所需软件 nginx-1.7.11.3-Gryphon&#xff08;这个包含必须的RTMP模块&#xff0c;普通的Ngxin没有这个&#xff09;ffmpegVLC 配置Nginx 1为Nginx配置RTMP和HLS 这里定义了一个叫live的RTMP路径。同时设置其开启HLS功能&#xff0c;那么所有推送到这个地址的RTMP流都会自动生…

AWS MSK集群认证和加密传输的属性与配置

通常&#xff0c;身份认证和加密传输是两项不相关的安全配置&#xff0c;在Kafka/MSK上&#xff0c;身份认证和加密传输是有一些耦合关系的&#xff0c;重点是&#xff1a;对于MSK来说&#xff0c;当启用IAM, SASL/SCRAM以及TLS三种认证方式时&#xff0c;TLS加密传输是必须的&…

C++STL库中的string

文章目录 STL库对于string类的介绍 string常用接口 string类的模拟实现 string对象大小的计算 写时拷贝 前言 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字…

青龙面板集合仓库(不断更新)青龙面板,京东定时任务库,脚本库大全

文章目录 文章目录前言简易一键安装脚本库最新京东比价小插件 文章目录 前言 Faker维护仓库&#xff0c;本地sign保证CK安全防泄漏&#xff0c;收集全网目前能正常使用的脚本。 全网能用的&#xff0c;本仓库都有。有问题进群反馈。 简易一键安装 最新版青龙有可能造成脚本…

软件测试技能提升自学,如何学?

又到了年底&#xff0c;对于我们测试同学来说&#xff0c;多多少少会立一些flag。我已经被连续打脸了好几年&#xff0c;生活为什么总是这么不易&#xff1f;好了&#xff0c;不扯远了&#xff0c;我们今天的主题是自学的那些事。 学习新的技能我相信是每一个测试同学都要面对…

使用MFC CAD 的一些使用方式记录【追加ing】

1. 项目调试&#xff1a;由于项目很大&#xff0c;因此&#xff0c;我们调试的时候&#xff0c;不应该编译整个软件而是应该只编译对应的 类去做处理 2. debug 设置断点方面&#xff1a; 以往我们的操作都是在.exe直接执行文件上进行操作&#xff0c;但是&#xff0c;现在&am…

解决虚拟机安装debian系统报错The failing step is: Select and install software

一波三折&#xff0c;一直卡在这一步&#xff0c;总是到不了流行度调查以及选择软件的界面。 下面是最终正确的步骤&#xff1a; 1&#xff0c;镜像源选项选择yes&#xff1b; 2&#xff0c;镜像源地区选择china&#xff1b; 3&#xff0c;镜像源地址可选mirrors.163.com&am…

Linux离线安装Jenkins、Maven、Gitlab、Git,部署Java项目

安装Java 《Linux安装java》 安装Maven 把Maven上传到Linux服务器/data/目录下进行解压 cd /data/ && tar -zxvf apache-maven-3.9.3-bin.tar.gz配置环境变量 vim /etc/profile找到export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL在下面追加 # mave…

【C语言】约分最简式

题目描述&#xff1a; 分数可以表示为分子/分母的形式。编写一个程序&#xff0c;要求用户输入一个分数&#xff0c;然后将其约分为最简分式。最简分式是指分子和分母不具有可以约分的成分了。如6/12可以被约分为1/2。当分子大于分母时&#xff0c;不需要表达为整数又分数的形…

基于 JIT 技术的开源全场景高性能 JSON 库

大家好&#xff0c;我是Mandy&#xff0c;上一节我们对Go中的切片数据类型进行了深度的剖析&#xff0c;今天给大家分享一个字节跳动自研开源的JSON数据解析包。一个速度奇快的 JSON 序列化/反序列化库&#xff0c;由 JIT &#xff08;即时编译&#xff09;和 SIMD &#xff08…

基于亚博K210开发板——LED(RGB)点灯

文章目录 开发板实验目的实验准备查看原理图软件对应SDKGPIO配置函数什么是 FPIOA 呢 实验代码LED/RGB驱动主程序控制 实验结果 开发板 实验目的 实现开发板上LED0、LED1以及RGB灯的点亮 实验准备 查看原理图 K210 开发板出厂默认已经焊接好 LED0 和 LED1。LED0 连接的是 IO…

Acrel-1000DP分布式光伏系统在重工企业的应用

安科瑞 崔丽洁 摘 要&#xff1a;分布式光伏发电特指在用户场地附近建设&#xff0c;运行方式以用户侧自发自用、余电上网&#xff0c;且在配电系统平衡调节为特征的光伏发电设施&#xff0c;是一种新型的、具有广阔发展前景的发电和能源综合利用方式&#xff0c;它倡导就近发电…