Java基础:建造者模式详解

建造者模式是一种创建型设计模式,其主要目的是将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。这种模式适用于创建那些包含多个组成部分、各部分之间有复杂的装配关系、且构造过程可能需要逐步进行或允许用户选择不同组件配置的产品对象。

结构与参与者

在建造者模式中,主要有以下几个关键角色:

  1. Product(产品类):定义了要构建的复杂对象的接口,通常包含多个组成部件。它不涉及具体的构建过程,仅定义产品的共有属性和行为。

  2. ConcreteProduct(具体产品类):实现了Product接口,是实际被构建的对象。

  3. Builder(抽象建造者):定义了一个包含一系列用于构建Product对象各个部件的抽象方法,通常还提供一个返回最终产品的接口(如getResult())。

  4. ConcreteBuilder(具体建造者):实现了Builder接口,负责实现构建过程的具体逻辑,即按照特定步骤创建并组装Product的各个部件。每个具体建造者都对应一种产品配置。

  5. Director(导演者/指挥者):负责协调建造过程,不直接参与对象的构建,而是通过调用Builder接口的方法来指导如何构建产品。它与具体的建造者解耦,使得客户端无需知道产品是如何被一步步构建出来的。

工作流程

  1. 客户端创建一个具体建造者(ConcreteBuilder)对象。
  2. 客户端通过Director以指定的步骤调用建造者的构建方法(如buildPartA(), buildPartB()等),逐步构建产品。
  3. 完成所有必要的构建步骤后,客户端可以通过建造者的getResult()方法获取最终构建好的Product对象。

示例说明

以创建一台电脑为例,我们可以定义如下类结构:

// Product: 电脑
public class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;

    // 构造函数私有化,防止外界直接创建
    private Computer(String cpu, String memory, String hardDisk) {
        this.cpu = cpu;
        this.memory = memory;
        this.hardDisk = hardDisk;
    }

    // 提供获取电脑配置的getter方法
    // ...

    // 其他电脑相关的功能方法...
}

// Builder: 抽象电脑建造者
public abstract class ComputerBuilder {
    protected Computer computer; // 用于保存中间构建结果

    public void createNewComputer() {
        computer = new Computer("", "", "");
    }

    public abstract void buildCPU(String cpu);
    public abstract void buildMemory(String memory);
    public abstract void buildHardDisk(String hardDisk);

    public Computer getComputer() {
        return computer;
    }
}

// ConcreteBuilder: 高配电脑建造者
public class HighEndComputerBuilder extends ComputerBuilder {
    @Override
    public void buildCPU(String cpu) {
        computer.setCPU(cpu);
    }

    @Override
    public void buildMemory(String memory) {
        computer.setMemory(memory);
    }

    @Override
    public void buildHardDisk(String hardDisk) {
        computer.setHardDisk(hardDisk);
    }
}

// Director: 电脑装配厂
public class ComputerFactory {
    public Computer constructComputer(ComputerBuilder builder) {
        builder.createNewComputer();
        builder.buildCPU("Intel i9");
        builder.buildMemory("32GB DDR5");
        builder.buildHardDisk("1TB SSD");
        return builder.getComputer();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        ComputerFactory factory = new ComputerFactory();
        ComputerBuilder builder = new HighEndComputerBuilder();

        Computer highEndComputer = factory.constructComputer(builder);
        System.out.println("Constructed high-end computer:");
        // 输出电脑配置...
    }
}

在这个例子中,Computer是产品类,ComputerBuilder是抽象建造者,HighEndComputerBuilder是具体建造者,ComputerFactory作为导演者角色,负责按照固定步骤调用建造者的构建方法来创建高配电脑。

适用场景

  1. 对象构造过程复杂:当一个对象的创建涉及多个步骤,这些步骤的顺序至关重要,或者某些步骤可能被省略,建造者模式能够清晰地封装这些复杂的构造逻辑。例如,创建一个包含多种零部件、配置选项多样的汽车、计算机或其他机械设备。

  2. 产品具有多种形态或配置:如果同一类型的产品可以根据客户需求或应用场景有不同的配置(如基础版、专业版、豪华版),每种配置对应一个具体建造者,这样可以方便地通过切换建造者来生成不同配置的产品,而无需在产品类中引入大量条件判断。

  3. 隔离复杂性:当产品类与创建过程过于复杂,以至于客户端代码难以理解或直接与之交互时,建造者模式可以将构建细节封装在建造者类中,使客户端只需与建造者接口交互,简化了客户端代码,同时隐藏了产品内部结构。

  4. 需要生成“零件列表”:在某些情况下,除了生成最终的产品对象外,还需要记录产品构建过程中使用的零件清单(如物料清单、成本计算等)。建造者模式可以在构建过程中收集这些信息,便于后续的报告生成或成本分析。

  5. 构建过程独立于产品组成部分:当构建过程独立于产品的具体组成部分(即构建算法与数据结构分离),且构建过程可能需要复用时,建造者模式能很好地分离这两部分,使得构建算法可以独立演化,提高代码的可维护性和扩展性。

  6. 需要支持递归构造:对于那些本身包含复杂树形结构或嵌套结构的产品(如XML文档、DOM树、菜单系统等),建造者模式可以自然地支持递归构造,通过递归调用建造者方法来构建嵌套结构。

  7. 需要延迟初始化:有时,出于性能、资源管理或依赖关系考虑,可能需要延迟初始化某些产品部件。建造者模式可以控制构建过程,确保在合适的时间点完成初始化。

存在的问题

尽管建造者模式能够有效地封装复杂对象的创建过程,但其使用也存在一些潜在问题:

  1. 代码膨胀:随着产品复杂性的增加,建造者类及其方法集可能会变得庞大,特别是当产品包含大量可选部件或配置时,可能会导致大量的建造者子类和构建方法。

  2. 过度设计:对于简单对象或者创建过程相对固定的场景,使用建造者模式可能会显得过于复杂,增加了不必要的抽象层次和类的数量。在这种情况下,简单的构造函数或者工厂方法可能就足够了。

  3. 灵活性与约束的平衡:为了保持构建过程的清晰和可控,建造者模式通常会限制客户端直接访问产品类的构造函数,这在一定程度上牺牲了灵活性。如果需要频繁改变产品的内部结构或添加新部件,可能需要修改建造者及其相关类。

  4. 适应变化的难度:当产品结构发生重大变化时,可能需要对所有的具体建造者进行相应的更新,这在大型项目中可能会带来一定的维护成本。

  5. 不适用动态产品结构:如果产品的组成部分或其组合方式在运行时才能确定,建造者模式可能不如其他动态生成对象的技术(如反射或脚本语言)灵活。

综上所述,建造者模式在处理复杂对象的创建、需要分步构建或支持多种不同配置的产品时非常有用,但应根据实际需求权衡其优点与可能带来的问题,避免在不需要复杂构建逻辑的情况下过度设计。

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

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

相关文章

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域 Tomcat 配置允许跨域Web 项目配置允许跨域Tomcat 同时允许静态文件和 Web 服务跨域 偶尔遇到一个 Tomcat 部署项目跨域问题,因为已经处理过…

企业微信hook接口协议,ipad协议http,外部联系人图片视频文件下载

外部联系人文件下载 参数名必选类型说明file_id是StringCDNkeyopenim_cdn_authkey是String认证keyaes_key是Stringaes_keysize是int文件大小 请求示例 {"url": "https://imunion.weixin.qq.com/cgi-bin/mmae-bin/tpdownloadmedia?paramv1_e80c6c6c0cxxxx3544d9…

设计模式-状态模式在Java中的使用示例-信用卡业务系统

场景 在软件系统中,有些对象也像水一样具有多种状态,这些状态在某些情况下能够相互转换,而且对象在不同的状态下也将具有不同的行为。 为了更好地对这些具有多种状态的对象进行设计,我们可以使用一种被称之为状态模式的设计模式…

【Android】android 10 jar_sdk_library添加

前言 当前项目遇到客户,Android 10 平台,需要封装jar_sdk_library给第三方应用使用。其中jar_sdk_library中存在aidl文件。遇到无法编译通过问题。 解决 system/tools/aidl修改 Android.bp修改

vue中web端播放rtsp视频流(摄像头监控视频)(海康威视录像机)

一、ffmpeg安装​​​​​​ ffmpeg下载 https://ffmpeg.org/download.html找ffmpeg-release-essentials.zip点击下载,下载完解压ffmpeg.exe 程序运行 二、配置ffmpeg环境变量 添加成功后验证是否生效任意地方打开cmd窗口输入 ffmpeg 打印如下表示成功 三、node…

Ribbon负载均衡器

1. 负载均衡器 目前主流的负载方案分为以下两种:(面试题) 1.1 服务端负载均衡 在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx&a…

【重磅开源】MapleBoot项目开发规范

基于SpringBootVue3开发的轻量级快速开发脚手架 🍁项目简介 一个通用的前、后端项目模板 一个快速开发管理系统的项目 一个可以生成SpringBootVue代码的项目 一个持续迭代的开源项目 一个程序员的心血合集 度过严寒,终有春日&#xff…

uniapp配置了pages.json 的 tabbar 国际化,小程序切换语言没有实时切换

如上图,按照uniapp官方文档配置了tabbar的国际化 但是微信小程序实时切换语言没有实时刷新 解决方案: 在App.vue中加入以下代码: 在onLaunch中执行方法即可

LLM大语言模型(十二):关于ChatGLM3-6B不兼容Langchain 的Function Call

背景 基于本地的ChatGLM3-6B直接开发LangChain Function Call应用,发现其输出的action和action_input非常不稳定。 表现为生成的JSON格式回答非常容易出现不规范的情况,导致LangChain的Agent执行报错,或者进入死循环。 ChatGLM3-6B不兼容La…

SQLAlchemy的使用

SQLAlchemy中filter函数的使用 https://blog.csdn.net/m0_67093160/article/details/133318889 创建临时字段 select id , CONCAT(‘内容’) AS fullname from example_table;

设计模式之外观模式

1、详细介绍 外观模式(Facade Pattern)是一种结构型设计模式,它为子系统的一组接口提供了一个统一的入口点(外观类)。外观模式简化了客户端与子系统之间的交互,屏蔽了子系统内部的复杂性,使客户…

【Unity】UnityEvent(一)

​UnityEvent----高效管理游戏事件的利器 在游戏开发中,事件系统是实现各种功能的关键组成部分。它允许我们将不同对象之间的交互解耦,使得代码更加模块化和易于维护。而UnityEvent作为Unity引擎提供的一种强大的事件系统工具,为开发者提供了…

c++ - 模板(一)

文章目录 一、函数模板 一、函数模板 1、概念 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本。 2、原理 函数模板是一个蓝图,它本身并不是函数,是编译器用…

宜搜科技死磕港交所上市:从搜索引擎到广告投放,业绩疲态凸显

近日,宜搜科技控股有限公司(下称“宜搜科技”)向港交所递交招股书,计划在香港主板上市,中银国际为其独家保荐人。 值得注意的是,宜搜科技已在资本市场辗转多年。该公司曾于2014年向纽交所递交上市申请&…

Web3与传统互联网:挑战、融合与共生

引言 Web3技术正以惊人的速度改变着我们的互联网体验。作为一个基于区块链的去中心化互联网模型,Web3不仅带来了创新和变革,还引发了与传统互联网之间的对比和讨论。本文将深入探讨Web3与传统互联网之间的关系,挑战,以及可能的融…

智慧火电厂合集 | 数字孪生助推能源革命

火电厂在发电领域中扮演着举足轻重的角色。主要通过燃烧如煤、石油或天然气等化石燃料来产生电力。尽管随着可再生能源技术的进步导致其比重有所减少,但直至 2023 年,火电依然是全球主要的电力来源之一。 通过图扑软件自主研发 HT for Web 产品&#xf…

模块三:二分——162.寻找峰值

文章目录 题目描述算法原理解法一:暴力查找解法二:二分查找 代码实现解法一:暴力查找解法二:CJava 题目描述 题目链接:162.寻找峰值 根据题意,需要使用O(log N)的时间复杂度来解决,得出本道题…

对浅拷贝的理解

问题背景 我之前一直以为浅拷贝出来的新对象和旧对象的引用地址是相同的,但是通过Object和发现浅拷贝的新对象和旧对象的引用地址不同!! const obj1 { name: "Alice", test: { age: 12 } };const obj4 Object.assign({}, obj1);…

linux中 虚拟机 修改时间 centos7

方法1 :虚拟机内 设置 方法2 代码实现 timedatectl set-timezone "Asia/Shanghai"

iOS 17上如何恢复数据?iOS 17 数据恢复软件

“您好,我正在为我的 iPhone 寻找一款iOS 17 数据恢复软件。升级到 iOS 17 后,我丢失了 iPhone 上的所有照片、联系人和消息。有什么建议吗?” ——丹尼 iOS 17数据恢复软件下载 升级到iOS 17后如何恢复丢失的数据?由于在 iPhone…
最新文章