【再探】设计模式—抽象工厂及建造者模式

 抽象工厂模式和建造者模式都属于创建型模式。两者都能创建对应的对象,而创建者模式更侧重于创建复杂对象,将对象的创建过程封装起来,让客户端不需要知道对象的内部细节。

1 抽象工厂模式

需求:

  1. 在使用工厂方法模式时,当增加新的产品类型时,需要创建对应的Factory类,这导致类的数量增加,让系统变得臃肿。
  2. 需要保证同风格下生成一致的组件。比如在写页面时,有dark及light模式,我们希望button、text等组件能在不同模式下保持一致的风格。抽象工厂模式介绍

1.1 抽象工厂模式介绍

为创建一组对象提供一组解决方案。与工厂模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,而是创建一族产品。

图 抽象工厂模式UML

public class Button {private final String color;public Button(String color) {this.color = color;}@Overridepublic String toString() {return getClass().getSimpleName() + "{" +"color='" + color + '\'' +'}';}
}public class Text {private final String color;public Text(String color) {this.color = color;}@Overridepublic String toString() {return getClass().getSimpleName() + "{" +"color='" + color + '\'' +'}';}
}public class DarkButton extends Button{public DarkButton(String color) {super(color);}
}public class DarkText extends Text{public DarkText(String color) {super(color);}
}public class LightButton extends Button{public LightButton(String color) {super(color);}
}public class LightText extends Text{public LightText(String color) {super(color);}
}
public interface ComponentsFactory {Button buildButton();Text buildText();}public class DarkComponentFactory implements ComponentsFactory{private final String color = "dark";@Overridepublic Button buildButton() {return new DarkButton(color);}@Overridepublic Text buildText() {return new DarkText(color);}}public class LightComponentFactory implements ComponentsFactory{private final String color = "light";@Overridepublic Button buildButton() {return new LightButton(color);}@Overridepublic Text buildText() {return new LightText(color);}
}

 

public class HtmlWeb {public static void main(String[] args) {ComponentsFactory componentsFactory = new DarkComponentFactory();System.out.println("-----------dark模式-----------");System.out.println(componentsFactory.buildButton());System.out.println(componentsFactory.buildText());System.out.println("-----------light模式-----------");componentsFactory = new LightComponentFactory();System.out.println(componentsFactory.buildButton());System.out.println(componentsFactory.buildText());}
}

1.1.1 优缺点

优点:

  1. 隔离类的实例化过程,使得客户端并不需要知道如何创建对象。
  2. 当不同产品族多个对象被设计成一起工作时,能保证客户端始终只使用同一个产品族的对象。
  3. 减少了工厂类的数量。
  4. 增加新的产品族方便,符合开闭原则。

缺点:

  1. 不符合单一职责原则,一个类创建了多个对象。
  2. 族群增加新的种类时,不符合开闭原则,需要修改全部的工厂类。

2 建造者模式

需求:

  1. 需要创建一个复杂的对象,隔离类的实例化过程,使得客户端不需要知道对象的内部细节。
  2. 创建对象时,对执行顺序有要求。

2.1 建造者模式介绍

将一个复杂对象的构建与它的表示分离,使得同样的构建过程,不同的构建顺序可以构建不同的表示。

图 构建模式UML

Director 为指挥者,用来控制Buider 的执行顺序,在实际开发中,这个角色经常会被省略,它的功能集成到Builder上;而Builder中的builderPart方法的返回值为它本身,这样就可以链式调用了。

public class JdbcConnector {private JdbcConnection connection;public void initConnection(URI uri) {connection = new JdbcConnection(uri);}public JdbcPreparedStatement getPreparedStatement(String query) {if (connection == null) throw new RuntimeException("连接器还未初始化");return connection.getPreparedStatement(query);}public static class JdbcConnection {public JdbcConnection(URI uri){System.out.println(uri);}public JdbcPreparedStatement getPreparedStatement(String query) {return new JdbcPreparedStatement(query);}}public static class JdbcPreparedStatement {String query;public JdbcPreparedStatement(String query) {this.query = query;}public String getResult() {return this.query;}}}public class JdbcConnectorBuilder {private String scheme;private String host;private String port;private String database;private String username;private String password;public JdbcConnectorBuilder setScheme(String scheme) {this.scheme = scheme;return this;}public JdbcConnectorBuilder setHost(String host) {this.host = host;return this;}public JdbcConnectorBuilder setPort(String port) {this.port = port;return this;}public JdbcConnectorBuilder setDatabase(String database) {this.database = database;return this;}public JdbcConnectorBuilder setUsername(String username) {this.username = username;return this;}public JdbcConnectorBuilder setPassword(String password) {this.password = password;return this;}/*** 产品*/private JdbcConnector jdbcConnector = null;public JdbcConnectorBuilder() {jdbcConnector = new JdbcConnector();}public JdbcConnector build() {StringBuilder sb = new StringBuilder("jdbc:");sb.append(scheme == null ? "mysql" : scheme).append("://");if (host == null) throw new RuntimeException("host不能为空");sb.append(host);sb.append(":").append(port == null ? "3306" : port);if (database == null) throw new RuntimeException("数据库不能为空");sb.append("/").append(database);try {URI uri = new URI(sb.toString());if (username == null || password == null) throw new RuntimeException("账号或密码错误");jdbcConnector.initConnection(uri);} catch (URISyntaxException e) {throw new RuntimeException("连接失败,连接信息有误");}return jdbcConnector;}}public class JdbcConnectionTest {public static void main(String[] args) {JdbcConnectorBuilder builder = new JdbcConnectorBuilder();builder.setScheme("mysql").setHost("localhost").setPort("3307").setDatabase("my-database").setUsername("root").setPassword("123456");JdbcConnector jdbcConnector = builder.build();JdbcConnector.JdbcPreparedStatement statement = jdbcConnector.getPreparedStatement("select * from student");System.out.println(statement.getResult());}
}

JDK 中的StringBuilder及Apache httpclient 的 URIBuilder 应用了建造者模式。

自定义StringBuilder

public class CustomStringBuilder {public static void main(String[] args) {CustomStringBuilder customStringBuilder = new CustomStringBuilder("hello customStringBuilder");for (int i =0; i < 100; i++) {customStringBuilder.append("---建造者模式---").append(i + "");}System.out.println(customStringBuilder);}char[] value;int count = 0;public CustomStringBuilder(int capacity) {value = new char[capacity];}public CustomStringBuilder(String str) {this(str.length() + 16);append(str);}CustomStringBuilder append(String str) {if (str == null) {throw new RuntimeException("字符串不能为空");}ensureCapacity(count + str.length());str.getChars(0,str.length(),value,count);count += str.length();return this;}private void ensureCapacity(int minCapacity) {if (minCapacity >= value.length) {value = Arrays.copyOf(value,value.length << 1);}}@Overridepublic String toString() {return new String(value,0,count);}
}

自定义URIBuilder

public class CustomURIBuilder {public static void main(String[] args) throws URISyntaxException {CustomURIBuilder customURIBuilder = new CustomURIBuilder();customURIBuilder.setHost("localhost").setPort("8080").setEncodedPath("/userinfo");customURIBuilder.appendQueryParam("username","hmf");customURIBuilder.appendQueryParam("status","1");customURIBuilder.appendQueryParam("createDate","2024/04/20");URI uri = customURIBuilder.build();System.out.println(uri);}private String scheme;private String host;private String port;private String encodedPath;private List<NameValuePair> queryParams;public CustomURIBuilder setScheme(String scheme) {this.scheme = scheme;return this;}public CustomURIBuilder setHost(String host) {this.host = host;return this;}public CustomURIBuilder setPort(String port) {this.port = port;return this;}public CustomURIBuilder setEncodedPath(String encodedPath) {this.encodedPath = encodedPath;return this;}public CustomURIBuilder appendQueryParam(String name,String value) {if (queryParams == null) queryParams = new ArrayList<>();queryParams.add(new NameValuePair(name,value));return this;}public URI build() throws URISyntaxException {return new URI(buildStr());}public String buildStr() {StringBuilder sb = new StringBuilder();if (this.scheme != null) sb.append(this.scheme).append("://");if (this.host == null) throw new RuntimeException("host不能为空");sb.append(this.host);if (this.port != null) sb.append(":").append(this.port);if (this.encodedPath != null) sb.append(this.encodedPath);if (this.queryParams != null) {for (int i = 0; i < this.queryParams.size(); i++) {sb.append(i == 0 ? "?" : "&").append(this.queryParams.get(i));}}return sb.toString();}private static class NameValuePair {String name;String value;public NameValuePair(String name, String value) {this.name = name;this.value = value;}@Overridepublic String toString() {if (this.value == null) return name;return name + "=" + value;}}}

2.1.1 优缺点

优点:

  1. 封装性好,将产品的内部表示与产品的生成过程分割开。客户端只需知道所需的产品类型,而不需要知道产品内部的具体结构和实现细节。
  2. 扩展性好,各个具体建造者相互独立,如果需要添加新的产品,只需创建对应的建造者即可,符合开闭原则。
  3. 便于构建发展对象,可以简化对象的创建过程,提高代码的可读性和可维护性。

缺点:

  1. 可维护性差,如果产品的内部发生变化,则对应的创建者可能需要修改的地方会比较多。
  2. 类的数量增加。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postgresql 从小白到高手 十一 :数据迁移ETL方案

文章目录 Postgresql 数据迁移ETL方案1、Pg 同类型数据库2 、Pg 和 不同数据库 Postgresql 数据迁移ETL方案 1、Pg 同类型数据库 备份 : pg_dump -U username -d dbname -f backup.sql插入数据&#xff1a; psql -U username -d dbname -f backup.sqlpg_restore -U username…

【Godot4.2】自定义Todo清单类 - myTodoList

概述 在写myList类的时候&#xff0c;就想到可以写一个类似的Todo清单类。 基础思路 本质还是在内部维护一个数组&#xff0c;在其基础上进行增删改查操作的封装为了方便存储数据&#xff0c;编写一个自定义内置类TodoItem&#xff0c;内部数组就变成了Array[TodoItem]类型的…

JENKINS 安装,学习运维从这里开始

Download and deployJenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their softwarehttps://www.jenkins.io/download/首先点击上面。下载Jenkins 为了学习&#xff0c;从windows开始&#x…

mysql-sql练习-5-行列互转

目录 成绩单 简单互转 需求 多行转多列 分组 判断 聚合 理解 分组 合并 逆向需求 多列转多行 输出 合并 abc 去重 合并 拆分 需求 建表 多行转多列 逆向需求 多列转多行 拆分 按长度 拆分 按个数 成绩单 简单互转 需求 多行转多列 分组 判断 聚合 with tmp as(--…

【快速入门 LVGL】-- 5、Gui Guider界面移植到STM32工程

上篇&#xff0c;我们已学习&#xff1a;【快速入门 LVGL】-- 4、显示中文 工程中添加了两个按钮作示范。运行效果如图&#xff1a; 本篇&#xff1a;把Gui Guider设计好的界面&#xff0c;移植到STM32工程。 特别地&#xff1a; 在使用Gui Guider进行界面设计时&#xff0c;应…

如何在Linux上安装Python?2024Python安装教程

在Linux上安装Python并不难&#xff0c;对于Ubuntu或Debian系统&#xff0c;使用命令sudo apt install python3&#xff1b;对于CentOS、Red Hat或Fedora系统&#xff0c;使用命令sudo yum install python3。 如何在Linux上安装Python&#xff1f; 确切的安装步骤有所不同&am…

LabVIEW 2024安装教程(附免费安装包资源)

鼠标右击软件压缩包&#xff0c;选择“解压到LabVIEW.2024”。 返回解压后的文件夹&#xff0c;鼠标右击“ni_labview-2024”选择“装载”。 鼠标右击“Install”选择“以管理员身份运行”。 点击“我接受上述2条许可协议”&#xff0c;然后点击“下一步”。 点击“下一步”。 …

用html画一个四叶草

<!DOCTYPE html> <html lang"en" > <head> <meta charset"UTF-8"> <title>四叶草</title> <link href"" rel"stylesheet"> <link rel"stylesheet" href"css/style.css&q…

xLua详解

目录 环境准备xLua导入 C#调用LuaLua解析器Lua文件加载重定向Lua解析管理器全局变量的获取全局函数的获取List和Dictionary映射table类映射table接口映射tableLuaTable映射table Lua调用C#准备工作Lua使用C#类Lua调用C#枚举Lua使用C# 数组 List 字典数组List字典 Lua使用C#扩展…

Ubuntu如何更换 PyTorch 版本

环境&#xff1a; Ubuntu22.04 WLS2 问题描述&#xff1a; Ubuntu如何更换 PyTorch 版本考虑安装一个为 CUDA 11.5 编译的 PyTorch 版本。如何安装旧版本 解决方案&#xff1a; 决定不升级CUDA版本&#xff0c;而是使用一个与CUDA 11.5兼容的PyTorch版本&#xff0c;您可…

22 重构系统升级-实现不停服的数据迁移和用户切量

专栏的前 21 讲&#xff0c;从读、写以及扣减的角度介绍了三种特点各异的微服务的构建技巧&#xff0c;最后从微服务的共性问题出发&#xff0c;介绍了这些共性问题的应对技巧。 在实际工作中&#xff0c;你就可以参考本专栏介绍的技巧构建新的微服务&#xff0c;架构一个具备…

图像处理的基本操作

一、PyCharm中安装OpenCV模块 二、读取图像 1、基本语法 OpenCV提供了用于读取图像的imread()方法&#xff0c;其语法如下&#xff1a; image cv2.imread&#xff08;filename&#xff0c;flags&#xff09; &#xff08;1&#xff09;image&#xff1a;是imread方法的返回…

前后缀分离,CF1209 C. Maximal Intersection

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1029C - Codeforces 二、解题报告 1、思路分析 线段相交具有可…

预编码算法学习笔记

文章目录 1. 基本原理2. 常见应用2.1 自编码器2.2 变分自编码器2.3 稀疏自编码器 3. 学习笔记 在机器学习领域&#xff0c;预编码算法是一种强大的工具&#xff0c;用于将高维数据映射到低维表示&#xff0c;从而提取数据中的重要特征。本文将介绍预编码算法的基本原理、常见应…

分布式与一致性协议之拜占庭将军问题(三)

拜占庭将军问题 叛将先发送消息 如果是叛将楚先发送作战消息&#xff0c;干扰作战计划&#xff0c;结果会有所不同吗&#xff1f; 在第一轮作战信息协商中&#xff0c;楚向苏秦发送作战指令"进攻",向齐、燕发送作战指令"撤退"&#xff0c;如图所示(当然还…

SpringCloud 学习笔记 —— 六、Ribbon:负载均衡(基于客户端)

SpringCloud 学习笔记 —— 一、背景-CSDN博客 SpringCloud 学习笔记 —— 二、微服务与微服务架构-CSDN博客 SpringCloud 学习笔记 —— 三、SpringCloud 入门概述-CSDN博客 SpringCloud 学习笔记 —— 四、SpringCloud Rest 学习环境搭建&#xff1a;服务提供者-CSDN博客 …

Linux 的静态库和动态库

本文目录 一、静态库1. 创建静态库2. 静态库的使用 二、动态库1. 为什么要引入动态库呢&#xff1f;2. 创建动态库3. 动态库的使用4. 查看可执行文件依赖的动态库 一、静态库 在编译程序的链接阶段&#xff0c;会将源码汇编生成的目标文件.o与引用到的库&#xff08;包括静态库…

对话访谈——五问RAG与搜索引擎:探索知识检索的未来

记一次关于RAG和搜索引擎在知识检索方面的对话访谈&#xff0c;针对 RAG 与传统搜索引擎的异同,以及它们在知识检索领域的优劣势进行了深入的探讨。 Q&#xff1a;传统搜索引擎吗&#xff0c;通过召回-排序的两阶段模式&#xff0c;实现搜索逻辑的实现&#xff0c;当前RAG技术也…

数字旅游:通过科技赋能,创新旅游服务模式,提供智能化、个性化的旅游服务,满足游客多元化、个性化的旅游需求

目录 一、数字旅游的概念与内涵 二、科技赋能数字旅游的创新实践 1、大数据技术的应用 2、人工智能技术的应用 3、物联网技术的应用 4、云计算技术的应用 三、智能化、个性化旅游服务的实现路径 1、提升旅游服务的智能化水平 2、实现旅游服务的个性化定制 四、数字旅…

想要接触网络安全,应该怎么入门学习?

作为一个网络安全新手&#xff0c;首先你要明确以下几点&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff1f;这一行职业前景如何&#xff1f; 其次&#xff0c;如果你现在不清楚学什么的话&…