面向对象设计模式:创建型模式之建造者模式

news2025/8/6 0:12:25

一、引入

在这里插入图片描述

Build:建造和构建具有建筑结构的大型物体

  • 建楼:打牢地基、搭建框架、然后自下而上一层层盖起来。
  • 构建物体:通常需要先建造组成这个物体的各个部分,然后分阶段把它们组装起来

二、建造者模式

2.1 Intent 意图

  • Separate the construction of a complex object from its representation so that the same construction process can create different representations. 将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的表示.

2.2 Applicability 适用性

  • the algorithm for creating a complex object should be independent of the parts that make up the object and how they’re assembled. 创建复杂对象的算法应该独立于组成对象的部分以及它们的组装方式.
    • 独立于:复杂对象的各个部分可能面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
  • the construction process must allow different representations for the object that’s constructed. 构造过程必须允许所构造对象的不同表示.

(将变与不变分隔开)

2.3 类图

在这里插入图片描述

  • Builder: specifies an abstract interface for creating parts of a Product object. 指定用于创建产品对象部件的抽象接口.
  • ConcreteBuilder:
    • Constructs and assembles parts of the product. 建造和组装产品的部分部件
    • Defines and keeps track of the representation it creates. 定义并跟踪它所创建的表示
    • Provides an interface (method) for retrieving the product. 提供了一个用于检索产品的接口(方法)
  • Director: constructs an object using the Builder interface. 使用 Builder 接口构造一个对象
  • Product: represents the complex object under construction. 表示正在构建的复杂对象

2.4 Collaborations 合作

  • The client creates the Director object and configures it with the desired Builder object.
    • new Director(new ConcreteBuilder())
  • Director notifies the builder whenever a part of the product should be built. Director 会告知 builder 何时应创建产品的(哪个)部件
    • constract()
      • buildPart(A)
      • buildPart(B)
      • buildPart(…)
  • Builder handles requests from the director and adds parts to the product. Builder 处理 director 的请求,添加部件到产品
  • The client retrieves the product from the builder. 客户端从 builder 取回产品.

2.5 建造者模式 VS 策略模式

  • In Builder pattern, Director decides the calling sequence of the methods in Builder. 在构建器模式中,Director 决定 Builder 方法的调用顺序.
  • In Template Method, the super class decides the calling sequence of the methods of subclass. 在模板方法中,超类决定子类的方法的调用顺序.

2.6 建造者模式实例:文档创建程序

  • Builder
public abstract class Builder {
    public abstract void makeTitle(String title);
    public abstract void makeString(String str);
    public abstract void makeItems(String[] items);
    public abstract void close();
}
import java.io.*;

public class HTMLBuilder extends Builder {
    private String filename;                                                        // 文件名
    private PrintWriter writer;                                                     // 用于编写文件的PrintWriter
    public void makeTitle(String title) {                                           // HTML文件的标题
        filename = title + ".html";                                                 // 将标题作为文件名
        try {
            writer = new PrintWriter(new FileWriter(filename));                     // 生成 PrintWriter
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"/>\n");
        writer.println("<html><head><title>" + title + "</title></head><body>");    // 输出标题
        writer.println("<h1>" + title + "</h1>");
    }
    public void makeString(String str) {                                            // HTML文件中的字符串
        writer.println("<p>" + str + "</p>");                                       // 用<p>标签输出
    }
    public void makeItems(String[] items) {                                         // HTML文件中的条目
        writer.println("<ul>");                                                     // 用<ul>和<li>输出
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }
    public void close() {                                                           // 完成文档
        writer.println("</body></html>");                                           // 关闭标签
        writer.close();                                                             // 关闭文件
    }
    public String getResult() {                                                     // 编写完成的文档
        return filename;                                                            // 返回文件名
    }
}

public class TextBuilder extends Builder {
    private String buffer = "";                                 // 文档内容保存在该字段中
    public void makeTitle(String title) {                       // 纯文本的标题
        buffer += "==============================\n";               // 装饰线
        buffer += "『" + title + "』\n";                            // 为标题加上『』
        buffer += "\n";                                             // 换行
    }
    public void makeString(String str) {                        // 纯文本的字符串
        buffer += "- " + str + "\n";                                // 为字符串添加
        buffer += "\n";                                             // 换行
    }
    public void makeItems(String[] items) {                     // 纯文本的条目
        for (int i = 0; i < items.length; i++) {
            buffer += " - " + items[i] + "\n";                     // 为条目添加?
        }
        buffer += "\n";                                             // 换行
    }
    public void close() {                                       // 完成文档
        buffer += "==============================\n";               // 装饰线
    }
    public String getResult() {                                 // 完成后的文档
        return buffer;
    }
}
  • Director
public class Director {
    private Builder builder;
    public Director(Builder builder) {              // 因为接收的参数是Builder类的子类
        this.builder = builder;                     // 所以可以将其保存在builder字段中
    }
    public void construct() {                       // 编写文档
        builder.makeTitle("Greeting");              // 标题
        builder.makeString("从早上至下午");         // 字符串
        builder.makeItems(new String[]{             // 条目
            "早上好。",
            "下午好。",
        });
        builder.makeString("晚上");                 // 其他字符串
        builder.makeItems(new String[]{             // 其他条目
            "晚上好。",
            "晚安。",
            "再见。",
        });
        builder.close();                            // 完成文档
    }
}
  • Main Test:
public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            usage();
            System.exit(0);
        }
        if (args[0].equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Director director = new Director(textbuilder);
            director.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (args[0].equals("html")) {
            HTMLBuilder htmlbuilder = new HTMLBuilder();
            Director director = new Director(htmlbuilder);
            director.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "文件编写完成。");
        } else {
            usage();
            System.exit(0);
        }
    }
    public static void usage() {
        System.out.println("Usage: java Main plain      编写纯文本文档");
        System.out.println("Usage: java Main html       编写HTML文档");
    }
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

不考虑分配与合并情况下,GO实现GCMarkSweep(标记清除算法)

观前提醒 熟悉涉及到GC的最基本概念到底什么意思&#xff08;《垃圾回收的算法与实现》&#xff09;我用go实现&#xff08;因为其他的都忘了&#xff0c;(╬◣д◢)&#xff91;&#xff77;&#xff70;!!&#xff09; 源码地址&#xff08;你的点赞&#xff0c;是我开源的…

基于鲸鱼算法优化SVM的发电功率回归预测,eemd-woa-svm

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 鲸鱼算法的原理及步骤 SVM应用实例,基于eemd分解+鲸鱼算法改进SVM的回归分析 代码 结果分析 展望 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在…

Linux中将多块新硬盘合并成一个,挂载到/mysqldata目录下

需求&#xff1a; 将两块空硬盘合并为“一块”&#xff0c;挂载到指定目录&#xff08;/data&#xff09;下&#xff0c;达到在一个目录使用2块硬盘所有空间的效果。 使用 fdisk -l 命令查看当前系统中的硬盘&#xff0c;如下图&#xff1a; 系统中存在两块未分配的硬盘&#…

< Linux > 进程信号

目录 1、信号入门 生活角度的信号 技术应用角度的信号 前台进程 && 后台进程 信号概念 用kill -l命令察看系统定义的信号列表 信号处理的方式 2、信号产生前 用户层产生信号的方式 3、产生信号 3.1、通过终端按键产生信号 3.2、核心转储core dump 3.3、调用系统函数…

目前全网最全Linux学习笔记

操作系统 用户和计算机的接口&#xff0c;同时也是计算机硬件和其他软件的接口&#xff1b; 用户程序是运行的操作系统之上&#xff1b; 功能&#xff1a; 管理计算机系统的硬件、软件及数据资源&#xff0c;控制程序运行&#xff0c;改善人机界面&#xff0c;为其他应用软…

6.4 深度负反馈放大电路放大倍数的分析

实用的放大电路中多引入深度负反馈&#xff0c;因此分析负反馈放大电路的重点是从电路中分离出反馈网络&#xff0c;并求出反馈系数 F˙\pmb{\dot F}F˙。 一、深度负反馈的实质 在负反馈放大电路的一般表达式中&#xff0c;若 ∣1A˙F˙∣>>1|1\dot A\dot F|>>1…

微服务之 CAP原则

文章目录微服务CAP原则AC 可用性 一致性CP 一致性 分区容错性AP 可用性 分区容错性提示&#xff1a;以下是本篇文章正文内容&#xff0c;SpringCloud系列学习将会持续更新 微服务CAP原则 经过前面的学习&#xff0c;我们对 SpringCloud Netflix 以及 SpringCloud 官方整个生…

Windows 上 执行docker pull命令 提示:The system cannot find the file specified.

错误提示error during connect: This error may indicate that the docker daemon is not running.: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/version": open //./pipe/docker_engine: The system cannot find the file specified.解决办法在cmd 窗口中执…

视觉SLAM十四讲ch7-1视觉里程计笔记

视觉SLAM十四讲ch7-1 视觉里程计笔记本讲目标从本讲开始&#xff0c;开始介绍SLAM系统的重要算法特征点法ORB特征BRIEF实践特征提取与匹配2D-2D&#xff1a;对极几何八点法求E八点法的讨论从单应矩阵恢复R&#xff0c;t小结三角化![在这里插入图片描述](https://img-blog.csdni…

网络割接概述

网络割接概述割接背景企业网络的变化割接概述割接难点割接的操作流程情景模拟及解决方案常见的割接场景割接背景 随着企业业务的不断发展&#xff0c;企业网络为了适应业务的需求不断的改造和优化。无论是硬件的扩容、软件的升级、配置的变更&#xff0c;凡是影响现网运行业务…

转速/线速度/角速度计算FC

工业应用中很多设备控制离不开转速、线速度的计算,这篇博客给大家汇总整理。张力控制的开环闭环方法中也离不开转速和线速度的计算,详细内容请参看下面的文章链接: PLC张力控制(开环闭环算法分析)_plc的收卷张力控制系统_RXXW_Dor的博客-CSDN博客里工业控制张力控制无处不…

十四届蓝桥选拔赛Scratch-2023.01.15 试题解析

十四届蓝桥选拔赛Scratch-2023.01.15 试题解析 单选题&#xff1a; 1. 运行以下程序&#xff0c;当角色被点击时会出现什么效果&#xff1f;&#xff08; C &#xff09; *选择题严禁使用程序验证&#xff0c;选择题不答和答错不扣分 A. 小猫说&#xff1a;“你好&#xff01…

前端脚手架搭建(part4)动态插入

例如控制模板的name、选择使用的插件&#xff0c;动态插入之前vue模板是有选择是否使用pinia、unocss&#xff0c;通过用户的选择&#xff0c;在项目中动态配置插件需要用到ejs读取模板&#xff0c;然后动态修改npm install ejs在libs/utils/index.js添加ejs模板的操作函数impo…

IOS - 抓包通杀篇

IOS中大多数情况&#xff0c;开发者都会使用OC提供的api函数&#xff0c;CFNetworkCopySystemProxySettings来进行代理检测&#xff1b; CFNetworkCopySystemProxySettings 检测函数直接会检测这些ip和端口等&#xff1a; 采用直接附加页面进程&#xff1a; frida -UF -l 通…

04 | 在OAuth 2.0中,如何使用JWT结构化令牌? 笔记

04 | 在OAuth 2.0中&#xff0c;如何使用JWT结构化令牌&#xff1f; JWT 结构化令牌 JSON Web Token&#xff08;JWT&#xff09;是一个开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑的、自包含的方式&#xff0c;用于作为 JSON 对象在各方之间安全地…

28个案例问题分析---10---对生产环境的敬畏--生产环境

一&#xff1a;背景介绍 1&#xff1a;上午9:23&#xff0c;老师没有进行上课&#xff0c;但是却又很多的在线人员&#xff0c;并且在线人员的时间也不正确。 2&#xff1a;开发人员及时练习用户&#xff0c;查看用户上课情况。 3&#xff1a;10点整&#xff0c;询问项目组长发…

BFD配置实验

BFD配置实验拓扑图静态路由联动BFDOSPF联动BFD拓扑图 其中地址各自配置自己的loopback接口&#xff0c;然后接口地址按照AB.1.1.X进行配置。 静态路由联动BFD AR1&#xff1a; [Huawei]bfd [Huawei]bfd 1 bind peer-ip 12.1.1.2 source-ip 12.1.1.1 auto [Huawei]ip route-st…

【强化学习】一文读懂,on-policy和off-policy

一文读懂&#xff0c;on-policy和off-policy 我来谈一下我的理解&#xff0c;不一定对。本文以 Sarsa 和 Q-learning 为例 Sarsa:on-policyQ-learning:off-policy 1. 什么是on-policy和off-policy&#xff1f; 我们有两个策略&#xff1a;行动策略和目标策略 on-policy: 行…

【python】为你绘制玫瑰一束,爱意永存

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 若是有真情&#xff0c;爱意如溪水&#xff0c; 若是有真爱&#xff0c;爱意如阳光&#xff0c; 若是两情相悦&#xff0c;又岂在朝朝暮暮&#xff0c; 女子淡淡的情愫&#xff0c;深深地想念&#xff0c; 浓浓的爱意&a…

Linux :理解编译的四个阶段

目录一、了解编译二、认识编译的四个阶段&#xff08;一&#xff09;预处理&#xff08;二&#xff09;编译&#xff08;三&#xff09;汇编&#xff08;四&#xff09;链接1.静态链接2.动态链接三、分步编译&#xff08;一&#xff09;创建.c文件&#xff08;二&#xff09;预…