3.创建型设计模式详解:生成器模式与原型模式的深度解析
设计模式(Design Patterns)是软件开发中常用的解决方案,帮助开发者处理常见的设计问题。创建型设计模式专注于对象的实例化,旨在提高系统的灵活性和可维护性。在这篇文章中,我们将深入探讨创建型设计模式中的生成器模式(Builder Pattern)和原型模式(Prototype Pattern),详细分析它们的应用场景、优缺点,并通过类图和综合案例加以对比。
1. 创建型设计模式概述
创建型设计模式包括以下几种常见模式:
- 单例模式(Singleton Pattern) 设计模式入门系列
- 工厂模式(Factory Patterns) 设计模式入门系列
- 简单工厂(Simple Factory)
- 工厂方法(Factory Method)
- 抽象工厂(Abstract Factory)
- 生成器模式(Builder Pattern)
- 原型模式(Prototype Pattern)
生成器模式和原型模式分别解决了对象创建过程中的复杂性和灵活性问题。接下来我们将重点讨论这两种模式。
2. 生成器模式(Builder Pattern)
2.1. 概述
生成器模式用于构建复杂对象,将对象的构建过程与其表示分离。通过使用生成器模式,用户可以一步一步地构建一个对象,而不必担心创建的顺序和复杂性。
2.2. 结构与实现
生成器模式通常包括以下几个关键角色:
- Builder: 定义构建产品各个部分的抽象接口。
- ConcreteBuilder: 实现Builder接口,构建并装配各个部分。
- Product: 表示被构建的复杂对象。
- Director: 指挥构建过程,使用Builder接口来构造复杂对象。
2.3. 优缺点
优点:
- 控制复杂构建过程: 提供了构建对象的详细步骤,能够精确控制对象的构建过程。
- 易于扩展: 可以通过不同的ConcreteBuilder类创建不同的对象表示。
缺点:
- 增加复杂性: 对于简单对象,生成器模式可能显得过于复杂。
- 依赖于Director: 需要额外的Director类来管理构建流程。
2.4. 应用场景
生成器模式适用于以下场景:
- 需要构建复杂对象,且该对象由多个部分组成。
- 构建过程需要按步骤进行,且各步骤有可能变化。
- 希望将对象的创建与表示分离,以支持多个表示。
3. 原型模式(Prototype Pattern)
3.1. 概述
原型模式通过复制现有对象来创建新对象,而不是通过实例化。该模式适用于需要创建大量相似对象的场景。
3.2. 结构与实现
原型模式的关键角色包括:
- Prototype: 声明一个克隆自身的接口。
- ConcretePrototype: 实现克隆接口,执行对象的浅拷贝或深拷贝。
- Client: 通过调用克隆方法来创建新的对象。
3.3. 优缺点
优点:
- 提高性能: 克隆对象比直接实例化对象更加高效,尤其是在创建复杂对象时。
- 简化对象创建: 通过克隆现有对象,可以避免使用构造函数创建对象的复杂性。
缺点:
- 深拷贝复杂: 深拷贝可能需要手动实现,并且复杂度较高。
- 潜在问题: 如果原型对象存在循环引用,克隆可能会引发问题。
3.4. 应用场景
原型模式适用于以下场景:
- 需要创建大量相似对象,并且实例化过程代价较高。
- 希望避免重复创建对象,并提高性能。
- 需要保存对象的状态,并在稍后恢复这些状态。
4. 生成器模式与原型模式对比
4.1. 区别
| 比较维度 | 生成器模式 | 原型模式 |
|---|---|---|
| 目标 | 分步骤构建复杂对象 | 通过克隆现有对象创建新对象 |
| 实现方式 | 将对象的构建过程封装在Builder和Director中 | 使用原型实例的克隆方法创建对象 |
| 使用场景 | 复杂对象构建 | 创建大量相似对象,避免复杂构造过程 |
| 优点 | 控制构建过程,支持多种表示 | 性能高效,简化对象创建 |
| 缺点 | 增加复杂性,依赖Director | 深拷贝复杂,可能引发克隆问题 |
4.2. 类图对比
生成器模式类图:
+---------------+| Director |+---------------+|v+---------------+| Builder |<---------------------++---------------+ || |+---------------+ +-----------------------------+| ConcreteBuilder|<------| ConcreteProduct |+---------------+ +-----------------------------+| |v v+-----------------------------+ +-----------------------------+| Product | | Product |+-----------------------------+ +-----------------------------+
原型模式类图:
+---------------+| Prototype |+---------------+|v+---------------------+| ConcretePrototype |+---------------------+|v+---------------------+| ClonedObject |+---------------------+
4.3. 案例对比
生成器模式案例:
假设我们在开发一个在线商店,需要构建不同类型的订单。每个订单包含客户信息、商品列表、付款方式、配送地址等。使用生成器模式,我们可以将构建过程分解成多个步骤,并根据需求选择不同的构建器来创建不同类型的订单。
原型模式案例:
如果我们需要为在线商店创建大量相似订单,例如为一个特定客户创建多个相同的订单,可以通过原型模式克隆一个现有订单,而不是重复构建新订单。这种方式可以大大提高效率,并减少冗余代码。
下面是一个简单的Java案例,展示了生成器模式和原型模式的使用。案例使用了订单管理的场景,分别展示如何用生成器模式构建复杂订单,以及如何用原型模式克隆订单。
1. 生成器模式案例
// 产品类:Order(订单)
public class Order {private String customerName;private String product;private int quantity;private String address;// 私有构造函数,确保只能通过生成器创建订单private Order(OrderBuilder builder) {this.customerName = builder.customerName;this.product = builder.product;this.quantity = builder.quantity;this.address = builder.address;}// 静态内部类:OrderBuilder(订单生成器)public static class OrderBuilder {private String customerName;private String product;private int quantity;private String address;public OrderBuilder setCustomerName(String customerName) {this.customerName = customerName;return this;}public OrderBuilder setProduct(String product) {this.product = product;return this;}public OrderBuilder setQuantity(int quantity) {this.quantity = quantity;return this;}public OrderBuilder setAddress(String address) {this.address = address;return this;}// 构建方法,返回Order实例public Order build() {return new Order(this);}}@Overridepublic String toString() {return "Order{" +"customerName='" + customerName + '\'' +", product='" + product + '\'' +", quantity=" + quantity +", address='" + address + '\'' +'}';}// 测试生成器模式的主方法public static void main(String[] args) {// 使用生成器模式构建一个订单Order order = new Order.OrderBuilder().setCustomerName("张三").setProduct("笔记本电脑").setQuantity(2).setAddress("北京市海淀区").build();System.out.println(order);}
}
2. 原型模式案例
// 产品类:Order(订单),实现Cloneable接口
public class Order implements Cloneable {private String customerName;private String product;private int quantity;private String address;public Order(String customerName, String product, int quantity, String address) {this.customerName = customerName;this.product = product;this.quantity = quantity;this.address = address;}// 克隆方法,实现浅拷贝@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}@Overridepublic String toString() {return "Order{" +"customerName='" + customerName + '\'' +", product='" + product + '\'' +", quantity=" + quantity +", address='" + address + '\'' +'}';}// 测试原型模式的主方法public static void main(String[] args) {try {// 创建一个订单Order originalOrder = new Order("李四", "智能手机", 3, "上海市浦东新区");// 克隆订单Order clonedOrder = (Order) originalOrder.clone();System.out.println("原订单: " + originalOrder);System.out.println("克隆订单: " + clonedOrder);} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}
代码解读
-
生成器模式: 通过
Order.OrderBuilder构建复杂的订单对象,可以灵活设置订单的各个属性,最终调用build()方法生成Order实例。适用于对象的创建过程涉及多个步骤,且每个步骤可能有不同的配置需求。 -
原型模式: 通过实现
Cloneable接口,并重写clone()方法,能够快速复制一个订单对象。适用于需要频繁创建相似对象的场景,能够提高创建效率,减少冗余代码。
5. 开发者的建议
-
选择合适的模式: 在实际开发中,根据项目需求和对象的复杂程度,选择合适的设计模式。如果对象创建非常复杂且有多个变种,可以考虑生成器模式;如果对象创建过程非常频繁且需要优化性能,原型模式是不错的选择。
-
结合其他模式使用: 生成器模式和原型模式并不孤立,它们可以结合其他设计模式(如工厂模式)使用,以进一步增强系统的灵活性和可维护性。例如,工厂模式可以与生成器模式结合,来创建复杂的对象。
-
关注对象的深拷贝和浅拷贝: 在使用原型模式时,务必理解并正确实现对象的深拷贝和浅拷贝,避免潜在的克隆问题。
通过本文的分析,我们详细探讨了生成器模式和原型模式的结构、应用场景、优缺点,并通过对比表格和类图来加深理解。无论是在构建复杂对象还是优化对象创建过程,这两种模式都能提供强大的支持。
相关文章:
3.创建型设计模式详解:生成器模式与原型模式的深度解析
设计模式(Design Patterns)是软件开发中常用的解决方案,帮助开发者处理常见的设计问题。创建型设计模式专注于对象的实例化,旨在提高系统的灵活性和可维护性。在这篇文章中,我们将深入探讨创建型设计模式中的生成器模式…...
goframe结构体标签和命令行标签
元数据gmeta 基础标签 更多了解:https://swagger.io/specification/ g.Meta path:"/profile" method:"get" summary:"展示个人资料页面" tags:"个人" g.Meta mime:"text/html" type:"string" example…...
pytest压力测试:不断发送数据,直到发现数据丢失
示例场景 假设有一个 send_data 函数接受数据并返回成功或失败的状态。 创建一个测试用例,通过逐步增加数据量来测试这个函数,直到返回失败为止。 步骤 定义压力测试函数 定义一个函数。不断发送数据,直到发现数据丢失。 创建 pytest 测试…...
自选择问题和处理效应模型
自选择问题和处理效应模型 DGP 注意: 这里的概率密度超过了1,这是正常的。概率密度的三原则,1是大于等于0;2是积分等于1;对于连续型随机变量,给定一个具体的x值,f(x)并不是该事件发生的概率。而…...
[数据集][目标检测]水面垃圾检测数据集VOC+YOLO格式2027张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2027 标注数量(xml文件个数):2027 标注数量(txt文件个数):2027 标注…...
OpenCV 之 模版匹配多个对象、图片旋转 综合应用
引言 在图像处理和计算机视觉中,模板匹配是一种常用的技术,用于在一幅较大的图像中查找与给定模板图像相似的部分。然而,在实际应用中,目标物体可能会出现在不同的角度,这就需要我们在匹配之前对模板进行旋转处理。本…...
ZooKeeper 中的 Curator 框架解析
Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细…...
机械学习—零基础学习日志(Python做数据分析02)
现在开始使用Python尝试做数据分析。具体参考的网址链接放在了文章末尾。 引言 我通过学习《利用Python进行数据分析》这本书来尝试使用Python做数据分析。书里让下载,anaconda,使用Jupyter来写代码,只是下载一个anaconda的确有点费时间&am…...
BRAM IP Native模式使用
简介 BRAM(Block RAM)是FPGA(Field-Programmable Gate Array)中的一种专用RAM资源,固定分布在FPGA内部的特定位置。该内容主要对BRAM(Block RAM”的缩写)Native模式下IP界面做详细描述和使用…...
react的useRef用什么作用
useRef 是 React 提供的一个钩子,用于在函数组件中创建和管理对 DOM 元素或组件实例的引用。它返回一个包含 current 属性的对象,可以用来存储对某个值的引用,而这个引用在组件的整个生命周期内保持不变。 useRef 的主要用途 1.访问 DOM 元素…...
10.2 TCP IP模型、IP协议、IPv4、子网掩码
TCP / IP 协议族 IP协议 IPv4地址 IPv4地址分类 子网掩码 子网掩码用来区分 网络地址 和 主机地址 真题 1...
工业相机飞拍的原理及工作原理
工业相机飞拍(或称为工业高速相机飞行拍摄)是一种利用高速图像捕捉技术和精密运动控制系统进行高效图像采集的先进技术。它广泛应用于工业检测、质量控制和自动化生产等领域。本文将详细探讨工业相机飞拍的原理及其工作方式。 一、工业相机飞拍的基本概…...
通过AI来创建一个_____html css网页制作成品 例子演示
使用AI 输入创建一个 html css网页制作成品 例 然后出来 好的,我将为您创建一个简单的HTML和CSS网页制作的示例。这个示例将包括基本的布局、文本样式和一些内联的CSS样式。 { "name": "dalle", "description": "A simple exa…...
C ++ 从单链表到创建二叉树到二叉树的遍历(结构体)
首先我们要了解二叉树的数据结构是什么,本质上二叉树是一个有两个节点的链表,我们先了解的单链表的相关定义 单链表 创建一个朴素的单链表 #include <iostream>using namespace std;struct Node{int val;Node* next;Node(int x) : val(x), next(…...
Python 编程:如何巧妙运用 `abc` 模块解锁面向对象设计的新维度?
引言 在软件开发的世界里,面向对象编程(OOP)作为一门艺术,其精髓在于通过封装、继承与多态来构建可维护性高、易于扩展的系统。而在 Python 这门语言中,abc 模块则为我们提供了一种优雅的方式来定义抽象基类ÿ…...
Jenkins 执行 shell 时报错 Host key verification failed.
1. 问题描述 在 jenkins 中执行下面的 shell 语句时 sshpass -p "123456" scp -r * dep192.168.1.100:/home/dep/Desktop/报错 Host key verification failed.可能原因是由于首次登录时需要输入 yes 导致无法连接成功。 The authenticity of host 192.168.1.100…...
MyBatis-Plus&Druid数据源
MyBatis-Plus(简称MP)和Druid数据源在Java开发中各自扮演着重要的角色,它们分别增强了MyBatis的数据库操作能力和提供了高效的数据库连接池管理。以下是对MyBatis-Plus和Druid数据源的总结: MyBatis-Plus 定义与特性:…...
MTPA控制分析与推导
目录 MTPA (Maximum torque per ampere) 一. 控制目的 二. 设计思路 三. 推导过程 MTPA (Maximum torque per ampere) 一. 控制目的 忽略电机中的铁耗只考虑铜耗的背景下,希望实现铜耗最小化。 二. 设计思路 通过给出电机在d-q坐标系下的等效电路模型&…...
Spring Boot 的Web项目如何直接显示html
前言 实际的开发中,在Spring Boot的Web项目中直接使用html文件的场景已经比较少了, 或者是只需要很简单的页面显示,或者是演示的需要, 大部分的状况都是Spring Boot作为后端提供REST 的服务,结合其他的一些前端Framework进行开发,比如VUE,Ext JS等。 Spring Boot项目中…...
【回收站选址】
题目 代码 #include <bits/stdc.h> using namespace std; const int R 2e91; typedef long long LL; unordered_set<LL> s; int piles[5]; int dx[4] {-1, 0, 1, 0}, dy[4] {0, 1, 0, -1}; int dx1[4] {-1, -1, 1, 1}, dy1[4] {-1, 1, -1, 1};bool check(LL …...
测试工程师用 Claude :它修得了选择器,修不了你的需求理解
测试架构这行有个一直没解决的尴尬:开发一周能写完的功能,QA 写测试要追两周。 你越想把覆盖率补齐,这个口子张得越大。 所以当 Claude Code 加上 Playwright 这套东西开始能"自己写测试"的时候, QA 圈子是真的盯着看。但我想先泼一句:它确实改变了一些事, 但改变的…...
5个步骤掌握ScriptHookV:GTA V脚本开发终极指南
5个步骤掌握ScriptHookV:GTA V脚本开发终极指南 【免费下载链接】ScriptHookV An open source hook into GTAV for loading offline mods 项目地址: https://gitcode.com/gh_mirrors/sc/ScriptHookV 你是否曾梦想过为GTA V创造属于自己的游戏模组?…...
Unity图表性能优化:从折线图到饼图的底层实现与避坑指南
1. 为什么Unity里做图表不是“加个UI控件”就完事了? 在Unity项目里,当策划甩来一句“这个数据面板加个折线图展示用户留存率”,或者美术提出“战斗结算页需要动态饼图显示伤害来源分布”,很多开发者第一反应是:去Asse…...
Open WebUI企业级部署指南:全功能AI平台架构与生产环境实践
Open WebUI企业级部署指南:全功能AI平台架构与生产环境实践 【免费下载链接】open-webui User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 项目地址: https://gitcode.com/GitHub_Trending/op/open-webui Open WebUI是一个功能强大的自托管A…...
3分钟学会:免费歌词制作工具让你轻松成为音乐剪辑高手 [特殊字符]
3分钟学会:免费歌词制作工具让你轻松成为音乐剪辑高手 🎵 【免费下载链接】lrc-maker 歌词滚动姬|可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 你是否曾经想为自己喜欢的歌曲制作…...
3大突破性技术:如何实现Cursor AI编程助手永久免费使用
3大突破性技术:如何实现Cursor AI编程助手永久免费使用 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…...
深度解析ZXing.Net:.NET生态中的企业级条码识别与生成解决方案
深度解析ZXing.Net:.NET生态中的企业级条码识别与生成解决方案 【免费下载链接】ZXing.Net .Net port of the original java-based barcode reader and generator library zxing 项目地址: https://gitcode.com/gh_mirrors/zx/ZXing.Net ZXing.Net作为Java版…...
在Taotoken模型广场中根据任务与预算选择合适的AI模型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在Taotoken模型广场中根据任务与预算选择合适的AI模型 当你准备将大模型能力集成到自己的应用或工作流中时,面对市场上…...
ARM编译器符号排列机制解析与工程实践
1. ARM编译器符号排列机制深度解析在嵌入式开发中,全局常量的内存布局往往会对系统行为产生微妙影响。最近在将项目从ARMCC v5迁移到ARMCLANG v6时,我遇到了一个有趣的差异现象:相同源代码中的const数组,在两个工具链中竟然产生了…...
免费开源神器:SMUDebugTool让你轻松掌控AMD Ryzen处理器的秘密
免费开源神器:SMUDebugTool让你轻松掌控AMD Ryzen处理器的秘密 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: ht…...
