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

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

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.mzph.cn/pingmian/5435.shtml

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

相关文章

Java File类

1. File类概述 1.1 什么是File类 File是java.io包下作为文件和目录的类。File类定义了一些与平台无关的方法来操作文件&#xff0c;通过调用File类中的方法可以得到文件和目录的描述信息&#xff0c;包括名称、所在路径、读写性和长度等&#xff0c;还可以对文件和目录进行新建…

从Paint 3D入门glTF

Paint 3D Microsoft Paint 3D是微软的一款图像编辑软件&#xff0c;它是传统的Microsoft Paint程序的升级版。 这个新版本的Paint专注于三维设计和创作&#xff0c;使用户可以使用简单的工具创建和编辑三维模型。 Microsoft Paint 3D具有直观的界面和易于使用的工具&#xff0…

GitLab常用指令!(工作中常用的)

目录 克隆代码创建分支切换分支将代码提交到分支当中Merge合并 克隆代码 复制完地址&#xff0c;打开Git Bash&#xff0c;然后 git clone “复制的地址”创建分支 创建new_test分支 git branch new_test切换分支 切换到new_test分支 git checkout new_test将代码提交到分…

Hotcoin Research | 市场洞察:2024年4月22日-28日

加密货币市场表现 本周内加密大盘整体呈现出复苏状态&#xff0c;在BTC减半后进入到震荡上行周期。BTC在$62000-66000徘徊&#xff0c;ETH在$3100-3300徘徊&#xff0c;随着港交所将于 4 月 30 日开始交易嘉实基金的比特币和以太坊现货 ETF&#xff0c;周末行情有一波小的拉升…

vue+elementUI实现点击左右箭头切换按钮功能

原本是可以用el-tabs做的,就像下面的样式,但是领导说不行 最后用button和element里面的el-carousel(走马灯)结合了一下 长这样 感觉还不错 可以自己改样式 代码如下: <div class"drawer-carousel"><el-carousel arrow"always" :loop"false…

自动驾驶框架 UniAD环境部署

感谢大佬们的开源工作 UniAD-github地址-YYDS更多bev算法部署参考如果您觉得本帖对您有帮助&#xff0c;感谢您一键三连支持一波^_^ 统一自动驾驶框架 (UniAD) &#xff0c;第一个将全栈驾驶任务整合到一个深度神经网络中的框架&#xff0c;并可以发挥每个子任务以及各个模块的…

NASA数据集——VIIRS每日 L3深蓝气溶胶网格产品(AERDB_D3_VIIRS_SNPP),以 1 x 1 度

VIIRS/SNPP Deep Blue Level 3 monthly aerosol data, 1 degree x1 degree grid 简介 美国国家航空航天局&#xff08;NASA&#xff09;的可见红外成像辐射计套件&#xff08;VIIRS&#xff09;标准三级&#xff08;L3&#xff09;每月深蓝气溶胶产品来自苏米国家极轨伙伴关系…

开通Jetbrains个人账号,赠送这些付费插件

开通Jetbrains个人账号&#xff0c;或者Jetbrains现成账号的, 可赠送以下付费插件 现成账号&#xff1a;https://web.52shizhan.cn/activity/xqt8ly 个人账号&#xff1a;https://web.52shizhan.cn/legal 账号支持全家桶系列&#xff1a;AppCode,CLion,DataGrip,GoLand,Intell…

WebAuthn 无密码身份认证

文章目录 WebAuthn简介工作原理组成部分架构实现注册认证应用场景案例演示 WebAuthn简介 WebAuthn&#xff0c;全称 Web Authentication&#xff0c;是由 FIDO 联盟&#xff08;Fast IDentity Online Alliance&#xff09;和 W3C&#xff08;World Wide Web Consortium&#x…

java技术栈快速复习05_基础运维(linux,git)

Linux知识总览 linux可以简单的理解成和window一样的操作系统。 Linux和Windows区别 Linux是严格区分大小写的&#xff1b;Linux中一切皆是文件&#xff1b;Linux中文件是没有后缀的&#xff0c;但是他有一些约定俗成的后缀&#xff1b;Windows下的软件一般是无法直接运行的Li…

如何安全可控的进行跨区域数据交换,提高数据价值?

跨区域数据交换指的是在不同地理位置或不同网络环境下的数据传输和共享。随着数字化转型的加速&#xff0c;企业及组织越来越依赖于数据的流动来优化业务流程、增强决策制定和推动创新。然而&#xff0c;跨区域数据交换也带来了一系列的挑战和风险&#xff0c;主要包括&#xf…

3款超好用的PDF在线处理神器,学会了职场工作效率翻倍!

&#x1f60a; 作为一名职场小白,我深知处理文档的痛苦。尤其是面对PDF这个"大魔王",经常感到头大! 合同要合并、简历要压缩、论文要转Word改格式…一个个来手动操作,简直要累死。&#x1f62b; 直到我发现了这些PDF在线处理神器!瞬间感觉自己的工作效率嗖嗖提升,整…

【STM32】F405/407的模块总览图,记录查看

从STM32F405/407数据手册中提取&#xff0c;方便以后查看。主要是什么外设连接在什么总线上&#xff0c;时钟频率是多少。 TIM2、3、4、5、12、13、14在APB1上&#xff0c;最大频率84M TIM1、8、9、10、11在APB2上&#xff0c;最大频率168M

3.9设计模式——Strategy 策略模式(行为型)

意图 定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使他们可以相互替换此模式使得算法可以独立于使用它们的客户而变化 结构 Strategy&#xff08;策略&#xff09;定义所有支持的算法的公共入口。Context使用这个接口来调用某ConcreteStrategy定义的方…

从源头上减少BUG:掌握Java中的label和assert语句!

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

【webrtc】MessageHandler 1: 基于线程的消息处理:以10毫秒处理音频为例

基于m98 G:\CDN\rtcCli\m98\src\audio\null_audio_poller.h分发的消息由MessageHandler 类通过其抽象接口OnMessage 实现处理 NullAudioPoller NullAudioPoller 是一个处理audio的消息的分发器 poll 启动:

手写一个uart协议——rs232(未完)

先了解一下关于uart和rs232的基础知识 文章目录 一、RS232的回环测试1.1模块整体架构1.2 rx模块设计1.2.1 波形设计1.2.2代码实现与tb1.2.4 仿真 1.3 tx模块设计1.3.1波形设计 本篇内容&#xff1a; 一、RS232的回环测试 上位机由串口助手通过 rx 线往 FPGA 发 8 比特数据&a…

DS高阶:图论基础知识

一、图的基本概念及相关名词解释 1.1 图的基本概念 图是比线性表和树更为复杂且抽象的结&#xff0c;和以往所学结构不同的是图是一种表示型的结构&#xff0c;也就是说他更关注的是元素与元素之间的关系。下面进入正题。 图是由顶点集合及顶点间的关系组成的一种数据结构&…

MATLAB - 机器人动力学 - 质心(Center of Mass)

系列文章目录 前言 一、用法 com centerOfMass(robot) com centerOfMass(robot,configuration) [com,comJac] centerOfMass(robot,configuration) 二、说明 com centerOfMass(robot) 计算机器人模型在原点构型处相对于基础坐标系的质心位置。com centerOfMass(robot,conf…

链表算法题总结

链表作为一个基础的数据结构&#xff0c;在开发中经常被使用。 链表往往使用如下的数据结构来表示&#xff0c;struct node 表示链表中的一个节点&#xff0c;data 表示节点的数据&#xff1b;next 表示这个节点指向的下一个节点&#xff0c;如果是链表的尾节点&#xff0c;那…