设计模式探索:建造者模式

news2024/11/14 19:19:17

1. 什么是建造者模式

建造者模式 (Builder Pattern),也被称为生成器模式,是一种创建型设计模式。

  • 定义:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式要解决的问题:

  • 建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无需知道其内部的具体构造细节。
    在这里插入图片描述

2. 建造者模式的结构

在这里插入图片描述

建造者(Builder)模式包含以下4个角色:

  1. 抽象建造者类(Builder):规定要实现复杂对象的哪些部分的创建,并不涉及具体的部件对象的创建。
  2. 具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供一个方法,返回创建好的复杂产品对象。
  3. 产品类(Product):要创建的复杂对象 (包含多个组成部件)。
  4. 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指挥者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建(客户端一般只需要与指挥者进行交互)。

3. 代码示例

下面是一个SQL查询生成器的例子,展示如何使用建造者模式生成不同数据库的SQL查询语句。

产品类
public class SqlQuery {
    private String select;
    private String from;
    private String where;
    private String groupBy;
    private String orderBy;
    private String limit;

    public SqlQuery(String select, String from) {
        this.select = select;
        this.from = from;
    }

    // Getters and setters

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("SELECT ").append(select).append(" FROM ").append(from);

        if (where != null && !where.isEmpty()) {
            sb.append(" WHERE ").append(where);
        }

        if (groupBy != null && !groupBy.isEmpty()) {
            sb.append(" GROUP BY ").append(groupBy);
        }

        if (orderBy != null && !orderBy.isEmpty()) {
            sb.append(" ORDER BY ").append(orderBy);
        }

        if (limit != null && !limit.isEmpty()) {
            sb.append(" LIMIT ").append(limit);
        }

        return sb.toString();
    }
}

抽象建造者

public abstract class SqlQueryBuilder {
    protected SqlQuery sqlQuery;

    public void createSqlQuery(String select, String from) {
        sqlQuery = new SqlQuery(select, from);
    }

    public SqlQuery getSqlQuery() {
        return sqlQuery;
    }

    public abstract void buildWhere();
    public abstract void buildGroupBy();
    public abstract void buildOrderBy();
    public abstract void buildLimit();
}

具体建造者

public class MySqlQueryBuilder extends SqlQueryBuilder {
    @Override
    public void buildWhere() {
        sqlQuery.setWhere("1 = 1"); // MySQL不需要限制行数
    }

    @Override
    public void buildGroupBy() {
        sqlQuery.setGroupBy("deptno, ename, hiredate");
    }

    @Override
    public void buildOrderBy() {
        sqlQuery.setOrderBy("hiredate DESC");
    }

    @Override
    public void buildLimit() {
        sqlQuery.setLimit("0, 10"); // MySQL分页从0开始
    }
}

public class OracleQueryBuilder extends SqlQueryBuilder {
    @Override
    public void buildWhere() {
        sqlQuery.setWhere("rownum <= 1000"); // Oracle查询最多返回1000行数据
    }

    @Override
    public void buildGroupBy() {
        sqlQuery.setGroupBy("deptno, ename, hiredate");
        sqlQuery.setSelect(sqlQuery.getSelect() + ", deptno, ename, hiredate");
    }

    @Override
    public void buildOrderBy() {
        sqlQuery.setOrderBy("hiredate");
    }

    @Override
    public void buildLimit() {
        sqlQuery.setLimit("10");
    }
}

指挥者类

public class SqlQueryDirector {
    private SqlQueryBuilder sqlQueryBuilder;

    public void setSqlQueryBuilder(SqlQueryBuilder sqlQueryBuilder) {
        this.sqlQueryBuilder = sqlQueryBuilder;
    }

    public void buildSqlQuery(String select, String from) {
        sqlQueryBuilder.createSqlQuery(select, from);
        sqlQueryBuilder.buildWhere();
        sqlQueryBuilder.buildGroupBy();
        sqlQueryBuilder.buildOrderBy();
        sqlQueryBuilder.buildLimit();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        // 创建MySQL建造者
        SqlQueryBuilder mySqlQueryBuilder = new MySqlQueryBuilder();

        // 创建Oracle建造者
        SqlQueryBuilder oracleQueryBuilder = new OracleQueryBuilder();

        // 指导者
        SqlQueryDirector sqlQueryDirector = new SqlQueryDirector();

        // 构建MySQL查询语句
        sqlQueryDirector.setSqlQueryBuilder(mySqlQueryBuilder);
        sqlQueryDirector.buildSqlQuery("*", "table1");

        SqlQuery mySqlQuery = mySqlQueryBuilder.getSqlQuery();
        System.out.println("MySQL Query: " + mySqlQuery);

        // 构建Oracle查询语句
        sqlQueryDirector.setSqlQueryBuilder(oracleQueryBuilder);
        sqlQueryDirector.buildSqlQuery("*", "table2");
        SqlQuery oracleQuery = oracleQueryBuilder.getSqlQuery();
        System.out.println("Oracle Query: " + oracleQuery);
    }
}

4. 建造者模式在实际开发中的应用

建造者模式在实际开发中的应用主要体现在以下几个方面:

  1. 复杂对象的创建:例如,在创建一个复杂对象时,如果这个对象有很多可选参数,使用建造者模式可以避免构造函数参数列表过长的问题。
  2. 多步骤创建过程:例如,在构建SQL查询、创建报告等需要多个步骤的过程中,使用建造者模式可以将这些步骤分离出来,使得代码更易于维护和扩展。
  3. 对象的不变性:例如,创建一个不可变对象时,可以使用建造者模式来确保对象在创建后不被修改。

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

  1. 工厂模式

    • 用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。
    • 主要关注的是创建单个对象。
      在这里插入图片描述
  2. 建造者模式

    • 用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。
    • 主要关注的是如何一步一步创建一个复杂的对象。
    • 更强调创建过程的分步和顺序。
      在这里插入图片描述

总之,建造者模式可以很好地解决创建复杂对象时的代码复用性和可维护性问题,而工厂模式则更加适用于创建一组相关的对象。

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

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

相关文章

Vue脚手架搭建及vue项目创建---大屏

灵感在于上数据可视化这门课程&#xff0c;需要做大屏系统。 下面是使用VS Code搭建vue脚手架并创建项目。 第一步 安装node.js和vscode node.js在官网下载后安装&#xff0c;安装后输入命令看是否安装好&#xff0c;若没安装好&#xff0c;自行去网上搜索怎么配置环境变量&a…

数据库SQL Server常用字符串函数

文章目录 字符串函数 字符串函数 CONCAT:拼接字符串 CONCAT(COLUMN1,_,COLUMN2) AS COLCONVERT&#xff1a;转换数据类型 CONVERT(data_type(length),data_to_be_converted,style)例如&#xff1a;CONVERT(VARCHAR(10),GETDATE(),110) SUBSTRING()&#xff1a;从字符串中返回…

动手实操微软开源的GraphRAG

微软在今年4月份的时候提出了GraphRAG的概念&#xff0c;然后在上周开源了GraphRAG,Github链接见https://github.com/microsoft/graphrag,截止当前&#xff0c;已有6900Star。 安装教程 官方推荐使用Python3.10-3.12版本&#xff0c;我使用Python3.10版本安装时&#xff0c;在…

快速上手:前后端分离开发(Vue+Element+Spring Boot+MyBatis+MySQL)

文章目录 前言项目简介环境准备第一步&#xff1a;初始化前端项目登录页面任务管理页面 第二步&#xff1a;初始化后端项目数据库配置数据库表结构实体类和Mapper服务层和控制器 第三步&#xff1a;连接前后端总结 &#x1f389;欢迎来到架构设计专栏~探索Java中的静态变量与实…

AutoHotKey自动热键(四)WINDOWS程序窗口的9种匹配方法与Window Spy窗口检索的使用方法

我们在进行窗口匹配的时候,根据匹配类型的不同可以多种匹配方法,根据使用者目录中可以找到九种匹配方式,这些匹配方式大都需自带的SPY监视工具用以查看窗口的名称.类名.进程名.句柄ID.位置信息等等 Window Spy的使用方法★★★ 软件界面 这个软件是安装好之后自带的一个脚本…

「API取数」FDL获取金蝶云星空的单据数据

很多企业的ERP系统都在用金蝶云星空&#xff0c;金蝶云星空API是IT人员获取数据的重要来源&#xff0c; 常常用来生成定制化报表&#xff0c;进行数据分析&#xff0c;或是将金蝶云的数据与OA系统、BI工具集成。 通常情况下&#xff0c;IT人员需要使用Python、Java等语言编写脚…

十款绚丽的前端 CSS 菜单导航动画

CSS汉堡菜单是一种非常流行的PC端和移动端web菜单风格&#xff0c;特别是移动端&#xff0c;这种风格的菜单应用更为广泛。这款菜单便非常适合在手机App上使用&#xff0c;它的特点是当顶部菜单弹出时&#xff0c;页面内容将会配合菜单出现适当的联动&#xff0c;让整个页面变得…

【UE Lua】 快速入门(基础语法、与UE引擎的交互)

目录 0 引言1 基础语法1.1 变量和数据类型1.2 注释1.3 控制结构1.4 函数1.5 表&#xff08;Table&#xff09;1.6 元表&#xff08;Metatable&#xff09;1.7 字符串操作1.8 模块和包1.9 错误处理 2 数据结构 - 表2.1 表&#xff08;Table&#xff09;2.2 元表&#xff08;Meta…

ElasticSearch学习篇14_《检索技术核心20讲》进阶篇之大倒排索引

背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243&#xff0c;文档形式记录笔记。 内容 主要是海量数据的大倒排索引的一些原理设计思想&#xff0c;ES底层就是基于这些设计思想以及原理&#xff0c;主要涉及读写分离、索引分层等…

【DFS(深度优先搜索)详解】看这一篇就够啦

【DFS详解】看这一篇就够啦 &#x1f343;1. 算法思想&#x1f343;2. 三种枚举方式&#x1f343;2.1 指数型枚举&#x1f343;2.2 排列型枚举&#x1f343;2.3 组合型枚举 &#x1f343;3. 剪枝优化&#x1f343;4. 图的搜索&#x1f343;5. 来几道题试试手&#x1f343;5.1 选…

淘宝扭蛋机小程序搭建全攻略

一、引言 在数字化时代&#xff0c;线上娱乐方式层出不穷&#xff0c;其中扭蛋机小程序以其独特的互动性和趣味性&#xff0c;受到了广大用户的喜爱。淘宝扭蛋机小程序作为其中的佼佼者&#xff0c;不仅为用户提供了丰富的奖品选择&#xff0c;还通过创新的玩法和营销策略&…

【计算机毕业设计】018基于weixin小程序实习记录

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Scrapy crawl spider 停止工作

Scrapy是一个用于爬取网站数据的流行框架&#xff0c;有时爬虫可能会停止工作&#xff0c;这通常是由多种原因引起的。以下是一些常见问题及其解决方法&#xff1a; 1、问题背景 用户在使用 Scrapy 0.16.2 版本进行网络爬取时遇到问题&#xff0c;具体表现为爬虫在运行一段时间…

OV SSL证书—防止钓鱼攻击的最佳证书

据Menlo Security日前发布的《2023年浏览器安全状况报告》&#xff0c;针对浏览器的高度规避自适应威胁&#xff08;HEAT&#xff09;呈现激增的发展趋势。 钓鱼攻击概率激增&#xff1a; 安全研究人员发现&#xff0c;与上半年相比&#xff0c;2023年下半年基于浏览器的网络…

大野耐一是如何为丰田铸就精益生产的?

在制造业的漫长历史中&#xff0c;无数的革新者和企业家为追求更高效、更精益的生产方式而不懈努力。其中&#xff0c;大野耐一的名字无疑是这段历史中最为耀眼的星辰之一。他&#xff0c;以其卓越的才智和坚韧的毅力&#xff0c;为丰田汽车公司铸就了一套享誉全球的精益生产体…

windows上部署python3.11

hello&#xff0c;大家好&#xff0c;我是一名测试开发工程师&#xff0c;至今已在自动化测试领域深耕9个年头&#xff0c;现已将本人实战多年的多终端自动化测试框架【wyTest】开源啦&#xff0c;在接下来的一个月里&#xff0c;我将免费指导大家使用wyTest&#xff0c;请大家…

软件安全性测试的工具有哪些?

软件安全性测试是确保软件系统在设计和实施过程中能够保护系统的机密性、完整性和可用性。为了进行软件安全性测试&#xff0c;有许多工具可供选择&#xff0c;这些工具可以帮助测试人员发现潜在的安全漏洞和弱点&#xff0c;从而提高软件系统的安全性。 以下是一些常用的软件安…

游戏提示找不到steam_api64.dll无法继续执行代码的处理方法

相信很多人在玩游戏时候打开游戏时候&#xff0c;经常会遇到各式各样的小问题&#xff0c;比如steam_api64.dll丢失或许找不到steam_api64.dll无法打开游戏就是其中常见问题之一&#xff0c;那么遇到steam_api64.dll丢失问题要如何解决呢&#xff1f;今天我就给大家详细分析一下…

无人直播怎么玩,一文带你了解AI小姐姐自动换装玩法

最近经常有小伙伴问我 就是像这种&#xff0c;一刷礼物&#xff0c;小姐姐就换装的视频到底该怎么做 今天就来教大家 如何来制作这种直播视频 第一步&#xff1a;搭建OBS 1、设置屏幕分辨率&#xff1a; 背景&#xff1a;因为一般初始状态&#xff0c;屏幕是横屏的&#xf…

【Linux】进程补充知识

文章目录 前言磁盘与物理内存 数据交互局部性原理页表 前言 磁盘是计算机唯一的一个机械设备&#xff0c;在磁盘文件系统中&#xff0c;我们了解到&#xff0c;磁盘的数据读取写入相比物理内存&#xff0c;CPU等效率低了很多。但是其作为数据的载体&#xff0c;物理内存与其交…