设计模式-原型模式详解
文章目录
- 前言
- 理论基础
- 1. 原型模式定义
- 2. 原型模式角色
- 3. 原型模式工作过程
- 4. 原型模式的优缺点
- 实战应用
- 1. 原型模式适用场景
- 2. 原型模式实现步骤
- 3. 原型模式与单例模式的区别
- 原型模式的变体
- 1. 带有原型管理器的原型模式
- 2. 懒汉式单例模式的原型模式实现
- 3. 细粒度原型模式
- 总结
前言
- 简介设计模式
- 设计模式是在软件开发中常见问题的解决方案,它们是经过实践和经验总结出来的可重用的设计思想和解决方案。设计模式通过提供通用的架构、原则和指导,帮助开发人员更有效地编写高质量的代码。
设计模式分为三个主要类别:
- 创建型模式:关注对象的创建过程,包括如何实例化对象,隐藏对象的创建细节以及对象的复制和克隆。
- 结构型模式:关注对象和类的组合方式,以实现更大结构的目标,例如类之间的关系。
- 行为型模式:关注类和对象间的交互和通信方式,以实现更好的协作和控制。
- 原型模式简介
原型模式是创建型模式的一种,它关注对象的复制和克隆。在某些情况下,通过传统的实例化方式创建新对象可能会非常昂贵或复杂。这时,原型模式提供了一种替代方法,通过克隆已有的对象来创建新对象,从而避免了昂贵的初始化过程。
原型模式通过使用克隆方法来生成新对象,可以节省资源和时间,并提高对象创建的效率。它适用于需要创建大量相似对象的场景,同时也具有良好的扩展性,可以根据需要通过继承和重写克隆方法来实现自定义的克隆逻辑。
总结起来,原型模式是一种通过克隆现有对象来创建新对象的设计模式。它提供了一种灵活、高效的对象创建方式,可以在某些场景下显著提高代码的复用性和可维护性。
理论基础
1. 原型模式定义
原型模式是一种创建型设计模式,它允许通过克隆现有对象来创建新对象,而无需依赖于传统的实例化过程。该模式通过复制现有对象的属性和状态,创建新的独立对象,并且可以根据需要修改其特定属性。
在原型模式中,我们定义一个抽象原型类,其中包含一个用于克隆对象的抽象方法。具体原型类则继承自抽象原型类,并实现了克隆方法,以便返回自身的克隆副本。客户端代码使用具体原型类的实例,并调用其克隆方法来创建新的对象。
原型模式的关键思想是通过已存在的对象来创建新的对象,而不是从头开始进行全新的实例化过程。通过克隆现有对象,可以避免重复的初始化工作和资源消耗,提高对象创建的效率。同时,原型模式也使得对象的创建更加灵活,可以根据需要进行修改和定制。
2. 原型模式角色
- 抽象原型类
- 具体原型类
- 客户端
3. 原型模式工作过程
4. 原型模式的优缺点
实战应用
1. 原型模式适用场景
- 对象初始化过程耗时较多
- 类初始化需要消耗很多资源
- 通过new的方式创建对象比较复杂
- 需要避免使用类的子类来进行初始化配置
2. 原型模式实现步骤
- 创建抽象原型类
- 创建具体原型类
- 创建客户端类
3. 原型模式与单例模式的区别
原型模式的变体
1. 带有原型管理器的原型模式
- 带有原型管理器的原型模式:
带有原型管理器的原型模式是对原型模式的扩展,它引入了一个原型管理器(Prototype Manager)来集中管理原型对象。原型管理器充当一个注册表,用于存储和获取各种原型对象。
这种变体的原型模式可以更方便地创建和管理多个不同类型的原型对象。客户端可以通过原型管理器获取所需的原型对象,而不需要自己显式地调用克隆方法。原型管理器可以在内部维护一个原型对象的集合,并根据需要进行复制和返回。
- 带有原型管理器的原型模式代码实现:
import java.util.HashMap;
import java.util.Map;// 原型接口
interface Prototype {Prototype clone();
}// 具体原型类 A
class ConcretePrototypeA implements Prototype {private String name;public ConcretePrototypeA(String name) {this.name = name;}public String getName() {return name;}@Overridepublic Prototype clone() {return new ConcretePrototypeA(this.name);}
}// 具体原型类 B
class ConcretePrototypeB implements Prototype {private int number;public ConcretePrototypeB(int number) {this.number = number;}public int getNumber() {return number;}@Overridepublic Prototype clone() {return new ConcretePrototypeB(this.number);}
}// 原型管理器
class PrototypeManager {private Map<String, Prototype> prototypes;public PrototypeManager() {prototypes = new HashMap<>();}public void registerPrototype(String key, Prototype prototype) {prototypes.put(key, prototype);}public Prototype getPrototype(String key) {Prototype prototype = prototypes.get(key);if (prototype != null) {return prototype.clone();}return null;}
}// 客户端
public class Main {public static void main(String[] args) {PrototypeManager manager = new PrototypeManager();manager.registerPrototype("A", new ConcretePrototypeA("Prototype A"));manager.registerPrototype("B", new ConcretePrototypeB(10));Prototype prototypeA = manager.getPrototype("A");if (prototypeA != null) {System.out.println("Clone A: " + ((ConcretePrototypeA) prototypeA).getName());}Prototype prototypeB = manager.getPrototype("B");if (prototypeB != null) {System.out.println("Clone B: " + ((ConcretePrototypeB) prototypeB).getNumber());}}
}
2. 懒汉式单例模式的原型模式实现
- 懒汉式单例模式的原型模式:
懒汉式单例模式是一种常见的单例模式实现方式,它延迟实例化单例对象,直到第一次使用时才创建。将懒汉式单例模式与原型模式结合起来,可以实现一种延迟加载并复用实例的模式。
在这种变体的原型模式中,单例对象充当原型对象,当客户端第一次请求获取实例时,会通过克隆来获得对象的副本,并将其作为单例对象返回。之后,每次请求都将返回这个已存在的副本,避免了重复的创建和初始化过程。
这种实现方式结合了懒加载和对象的复用,可以在需要的时候动态创建新对象并缓存起来,提高了系统的性能和资源利用率。
- 懒汉式单例模式的原型模式代码实现:
// 单例类
class Singleton {private static Singleton instance;// 私有构造函数private Singleton() {System.out.println("Singleton instance created.");}// 获取单例对象public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}// 克隆方法@Overrideprotected Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException("Cannot clone a singleton object.");}
}// 客户端
public class Main {public static void main(String[] args) {Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();System.out.println("Singleton 1: " + singleton1);System.out.println("Singleton 2: " + singleton2);// 尝试克隆单例对象try {Singleton clone = (Singleton) singleton1.clone();System.out.println("Clone: " + clone);} catch (CloneNotSupportedException e) {System.out.println(e.getMessage());}}
}
3. 细粒度原型模式
- 细粒度原型模式:
细粒度原型模式是指将一个复杂对象拆分成多个部分,并为每个部分创建对应的原型对象。这样,在需要使用某个部分时,只需要克隆该部分的原型对象即可,而不需要克隆整个复杂对象。
细粒度原型模式可以提高系统的灵活性和效率。它允许客户端选择需要的部分进行克隆,而不需要克隆整个对象。同时,当某个部分发生变化时,只需要修改对应的原型对象,而不需要重新创建整个对象。
这种模式适用于那些由多个组件或模块组成的复杂对象。通过细粒度的原型对象,可以更加灵活地构建和修改复杂对象的组成部分,减少了代码的重复和耦合度。
- 细粒度原型模式代码
// 原型接口
interface Prototype {Prototype clone();
}// 具体原型类 A
class ConcretePrototypeA implements Prototype {private String name;public ConcretePrototypeA(String name) {this.name = name;}public String getName() {return name;}@Overridepublic Prototype clone() {return new ConcretePrototypeA(this.name);}
}// 具体原型类 B
class ConcretePrototypeB implements Prototype {private int number;public ConcretePrototypeB(int number) {this.number = number;}public int getNumber() {return number;}@Overridepublic Prototype clone() {return new ConcretePrototypeB(this.number);}
}// 客户端
public class Main {public static void main(String[] args) {Prototype prototypeA = new ConcretePrototypeA("Prototype A");Prototype cloneA = prototypeA.clone();if (cloneA instanceof ConcretePrototypeA) {System.out.println("Clone A: " + ((ConcretePrototypeA) cloneA).getName());}Prototype prototypeB = new ConcretePrototypeB(10);Prototype cloneB = prototypeB.clone();if (cloneB instanceof ConcretePrototypeB) {System.out.println("Clone B: " + ((ConcretePrototypeB) cloneB).getNumber());}}
}
总结
- 原型模式使用总结
- 原型模式对于软件开发的重要性
// 抽象原型类
abstract class Prototype implements Cloneable {public abstract Prototype clone();
}// 具体原型类
class ConcretePrototype extends Prototype {@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}// 客户端
public class Client {public static void main(String[] args) {ConcretePrototype prototype = new ConcretePrototype();ConcretePrototype clone = (ConcretePrototype) prototype.clone();// 进行操作}
}
以上代码展示了原型模式的简单实现,其中抽象原型类定义了一个抽象方法clone,在具体原型类中实现了这个方法,并通过调用super.clone()方法进行对象的克隆。在客户端中,可以创建一个原型对象并进行克隆,从而得到一个新的对象进行操作。
原型模式适用于需要创建大量相似对象的场景,通过克隆已有对象来提高效率。它简化了对象的创建过程,减少了重复的初始化操作。同时,原型模式也具有良好的可扩展性,可以通过继承和重写clone方法来实现自定义的克隆逻辑。
总的来说,原型模式是一种简单而实用的设计模式,在软件开发中具有广泛的应用价值。通过合理地运用原型模式,可以提高代码的复用性、可维护性和灵活性,从而提高软件开发的效率和质量。
相关文章:

设计模式-原型模式详解
文章目录 前言理论基础1. 原型模式定义2. 原型模式角色3. 原型模式工作过程4. 原型模式的优缺点 实战应用1. 原型模式适用场景2. 原型模式实现步骤3. 原型模式与单例模式的区别 原型模式的变体1. 带有原型管理器的原型模式2. 懒汉式单例模式的原型模式实现3. 细粒度原型模式 总…...

大语言模型之七- Llama-2单GPU微调SFT
(T4 16G)模型预训练colab脚本在github主页面。详见Finetuning_LLama_2_0_on_Colab_with_1_GPU.ipynb 在上一篇博客提到两种改进预训练模型性能的方法Retrieval-Augmented Generation (RAG) 或者 finetuning。本篇博客过一下模型微调。 微调:…...
房地产行业专题报告:日本房地产市场借鉴
目录 1. 日本房地产泡沫的形成与崩溃 1.1 背景:实际需求减弱、宽松货币和弱金融监管推动泡沫形成 1.1.1 宏观环境:日本 80 年代起生育率降低,房地产基本面支撑力不足 1.1.2 货币政策:宽松货币政策叠加金融自由化促进泡沫生成 1.1.3 助推因素:企业积极参与土地投机、股…...

Educational Codeforces Round 154 (Rated for Div. 2)
Educational Codeforces Round 154 (Rated for Div. 2) A. Prime Deletion 思路: 因为1到9每个数字都有,所以随便判断也质素即可 代码 #include<bits/stdc.h> using namespace std; #define int long long #define rep(i,a,n) for(int ia;i<…...
elasticsearch批量删除(查询删除)
注:delete by query只适用于低于elasticsearch2.0的版本(不包含2.0)。有两种形式: 1.无请求体 curl -XDELETE localhost:9200/twitter/tweet/_query?quser:kimchy 2.有请求体 使用请求体的时候,请求体中只能使用query查询,不能使用filter curl -XD…...

容器技术Linux Namespaces和Cgroups
对操作系统了解多少,仅仅敲个命令吗 操作系统虚拟化(容器技术)的发展历程 1979 年,UNIX 的第 7 个版本引入了 Chroot 特性。Chroot 现在被认为是第一个操作系统虚拟化(Operating system level virtualization&#x…...
GO语言圣经 第四章习题
练习4.1 编写一个函数,计算两个SHA256哈希码中不同bit的数目。(参考2.6.2节的PopCount函数。) func PopCount(ptr *[32]byte) int {var res intfor i : 0; i < 32; i {x : int(ptr[i])for x ! 0 {res x & 1x >> 1}}return res }练习4.2 编…...
远程连接Ubuntu 22.04
远程连接Ubuntu 22.04 安装openssh-server sudo apt install openssh-server检查服务运行状态 systemctl status sshd重启服务状态 sudo systemctl restart ssh开启防火墙 sudo ufw enable开启ssh传输端口 sudo ufw allow ssh设置开机启动服务 sudo systemctl enable ssh配置服…...

字节前端实习的两道算法题,看看强度如何
最长严格递增子序列 题目描述 给你一个整数数组nums,找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7…...

设计模式—策略模式
目录 一、定义 二、特点 三、优点 四、缺点 五、实例 六.涉及到的知识点 1、一个类里面有哪些东西? 2、类和实例 什么是类? 什么是实例? 什么是实例化? 3、字段和属性 什么是字段? 属性是什么࿱…...

LPDDR4、DDR4
核心信息: 2400Mbps(每秒传输2400*1百万bit) 2400MT/s(百万次/秒) 信号...

ESP32C3 LuatOS RC522①写入数据并读取M1卡
LuatOS RC522官方示例 官方示例没有针对具体开发板,现以ESP32C3开发板为例。 选用的RC522模块 ESP32C3-CORE开发板 注意ESP32C3的 SPI引脚位置,SPI的id2 示例代码 -- LuaTools需要PROJECT和VERSION这两个信息 PROJECT "helloworld" VERSIO…...

MusicBrainz Picard for Mac :音乐文件ID3编辑器
MusicBrainz Picard for Mac是一款macOS平台的音乐文件ID3编辑器,能够帮助我们在Mac电脑上编辑音乐文件的ID3标签信息,包括艺人、专辑等信息,非常快速和简单方便。Picard是下一代MusicBrainz标记应用程序。 这个新的标签概念是面向专辑的&…...
❤ Uniapp使用
❤ Uniapp使用 一、介绍 uni-app官网:https://uniapp.dcloud.io/api/media/image?idpreviewimage 微信小程序官网:https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html 二、使用 1、uniapp 实现图片预览 单图预…...

解密Spring事务生效的内部机制
声明式事务和编程式事务对比: 声明式事务: 使用注解或XML配置的方式,在代码中声明事务的属性和行为。通过AOP和代理模式实现,将事务管理与业务逻辑代码解耦。适用于大多数情况,简化了代码,提高了可维护性和…...

大数据时代下的数据安全防护
随着大数据时代的来临,数据安全防护成为了一个重要的问题。在大数据时代,数据的规模和价值都得到了极大的提升,因此数据安全的重要性也变得越来越突出。本文将从数据加密、访问控制、网络安全和人员管理四个方面来介绍大数据时代下的数据安全…...

RabbitMQ-常用命令
RabbitMQ常用命令 3.1 启动停止rabbitMQ命令 # 前台启动Erlang VM 和 RabbitMQ 当窗口关闭或者ctrlc时,使退出了。 rabbitmq-server# 使用系统命令启动 systemctl start rabbitmq-server# 后台启动 rabbitmq-server -detached# 停止rabbitMQ和Erlang VM rabbitmq-…...
Spring中依赖注入的继承bean的细节问题
介绍 有时我们会对一种类型的bean进行继承,在Spring生成bean的时候,返回类型有时是子类类型,有时会父类类型。那么到底在什么情况下用哪种类型呢?肯定有不少人会忽略这点,本篇文章就是把这个细节讲清楚 案例 父类Ba…...
海外腾讯云服务器手机上无法访问外网怎么办??
本文将介绍腾讯云服务器无法访问外网的一些常见原因以及解决办法,同时解答了手机无法访问腾讯云服务器的问题。 腾讯云服务器(Tencent Cloud Server)是一种基于云计算技术的虚拟服务器,可以满足用户对于计算、存储、网络等方面的需…...

python3+requests:接口自动化测试(二)
前言:上篇文章python3requestsunittest:接口自动化测试(一):已经介绍了基于unittest框架的实现接口自动化,但是也存在一些问题,比如最明显的测试数据和业务没有区分开,接口用例不便于…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑 在电子商务领域,转化率与网站性能是决定商业成败的核心指标。今天,我们将深入解析不同类型电商平台的转化率基准,探讨页面加载速度对用户行为的…...