【原型模式】详解

一.概念

原型模式是一种创建型设计模式,它的主要思想是通过复制现有对象来创建新对象,而不是通过实例化一个类来创建。在原型模式中,我们称被复制的对象为原型(Prototype),新创建的对象为克隆体(Clone)。
在Java中,使用原型模式可以通过实现Cloneable接口和重写Object类的clone()方法来实现。
以下是原型模式的工作原理:

  1. 首先,需要定义一个需要克隆的原型类,并实现Cloneable接口。
  2. 在Cloneable接口中定义了一个clone()方法,该方法返回一个与原型对象相同的新对象。
  3. 当需要创建新对象时,可以先通过调用原型对象的clone()方法来创建一个新对象,然后再根据需要修改新对象的属性。
    优缺点
    原型模式的优点包括:
  4. 提高对象创建效率:使用原型模式创建对象比使用new方法创建对象更加高效,因为克隆操作不需要进行类的初始化等操作。
  5. 简化对象的创建过程:原型模式可以简化创建对象的过程,避免了重复创建相似对象的过程。
  6. 支持动态配置:可以根据需要进行动态配置,即根据原型对象创建多个变体对象。
    原型模式的缺点包括:
  7. 克隆对象破坏单一职责原则:克隆对象需要对原型对象的属性进行拷贝,这可能会导致对象破坏单一职责原则。
  8. 克隆对象需要与原型类保持一致:克隆对象需要与原型对象保持一致,否则可能会导致不一致的状态。

二.原型模式详解

原型模式结构
在这里插入图片描述

原型模式包含以下3个角色:
Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类也可以是接口,甚至还可以是具体实现类。
ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
Client(客户类):在客户类中,让一个原型对象克隆自身从而创建一个新的对象,只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。
深克隆与浅克隆
深拷贝与浅拷贝
原型模式使用
通用实现方法
抽象原型类代码:

public abstract class Prototype {public abstract Prototype clone();
}

具体原型类代码

public class ConcretePrototype extends Prototype {private String name; // 成员变量public void setName(String name) {this.name = name;}public void getName() {return this.name;}// 克隆方法实现public Prototype clone() {Prototype prototype = new ConcretePrototype(); // 创建新对象prototype.setName(this.name);return prototype;}
}

java语言中clone()和cloneable接口
所有java类均继承自java.long.Object类,Object类提供了一个clone方法,可以将一个java对象复制一份。因此在java中可以直接使用Object提供clone方法来实现对象的浅克隆
注意能实现克隆的java类都必须实现一个标识接口Cloneable,表示这里java类支持被复制。如果没有实现这个接口调用clone方法,java编译器将抛出CloneNotSupportedException异常:

public class ConcretePrototype implements Cloneable {public Prototype clone() {Object object = null;try {object = super.clone(); // 浅克隆} catch (CloneNotSupportedException exception) {System.err.println("Not support Cloneable");}return (Prototype)object;}
}

为了获取对象的一个克隆,可以直接利用Object类的clone方法:

  1. 在派生类中覆盖基类的clone方法,声明为public
  2. 在派生了中的clone方法中调用super.clone
  3. 派生类需要实现Cloneable接口
    应用举例
    题目:
    某数据处理软件需要增加一个图表复制功能。在图表对象(DataChart)中包含一个数据集对象(DataSet)。数据集对象用于封装要显示的数据,用户可以通过界面上的复制按钮将该图表复制一份,复制后,即可得到新的图表对象,然后可以修改新图表的编号、颜色、数据。试用原型模式设计软件实现深克隆。
    在这里插入图片描述

DataChart 类包含一个 DataSet 对象,在复制 DataChart 对象的同时将
复制 DataSet 对象,因此需要使用深克隆技术,可使用流来实现深克隆。其中Serializable是java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。故我们实现这个接口即可使用流来实现深克隆

三.原型管理器

原型管理器实现
原型管理器(Prototype Manager)是将多个原型对象存储在一个集合中供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象, 如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得。 在原型管理器中针对抽象原型类进行编程,以便扩展。 其结构如图所示:
在这里插入图片描述

其中原型管理器ProtptypeManager类的实现代码如下

package prototype_pattern;import java.util.Hashtable;/*** @author Cnc_hzf* @date 2022/4/22 15:00*/
public class PrototypeManager {private Hashtable prototypeTable = new Hashtable(); // 使用Hashtable存储原型对象public PrototypeManager() {prototypeTable.put("A", new ConcretePrototypeA());prototypeTable.put("B", new ConcretePrototypeB());}public void add(String key, Prototype prototype) {prototypeTable.put(key, prototype);}public Prototype get(String key) {Prototype clone = ((Prototype) prototypeTable.get(key)).clone(); // 通过克隆方法创建新对象return clone;}
}

在实际开发中可以将PrototypeManger设计为单例类,确保系统中有且仅有一个PrototypeManager对象,这样既有利于节省系统资源,还可以更好地对原型管理器对象进行控制。
原型管理器应用举例
问题描述:
某公司需要创建一个公文管理器,公文管理器中需要提供一个集合对象来存储一些公文模板,用户可以通过复制这些模板快速的创建新的公文,试使用带有原型管理器的原型模式来设计该公文管理器并使用Java代码编程模拟。
在这里插入图片描述

其中,OfficialDocument (抽象公文类)充当抽象原型类,其子类 FAR(Feasibility Analysis
Report,可行性分析报告)和 SRS(Software Requirements Specification,软件需求规格说明书)充当具体原型类,PrototypeManager 充当原型管理器。

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

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

相关文章

用户画像知识点补充——多数据源

引入 针对用户画像项目来说(产品)必须要支持从多种数据源加载业务数据,构建用户标签。 在之前的标签模型开发中,主要是为了简化开发复杂度,业务数据统一存储到HBase表中。 数据源包含如下几个方面: 存储H…

【应用层】 DNS 域名协议解析

文章目录 DNS(Domain Name System)出现及演化 ⏳DNS 概括🔍DNS定义DNS 作用 DNS工作原理⚙️域名解析DNS解析的详细工作流程 DNS域名解析方式🔄静态DNS域名解析动态DNS域名解析 DNS域名解析过程的深入分析 🧐递归查询迭代查询 公共DNS服务器的…

Tailwindcss Flex 布局相关的样式类及其实战案例

007 Flex布局相关的样式 flex-basics 相关的样式类 ClassPropertiesbasis-0flex-basis: 0px;basis-1flex-basis: 0.25rem; /* 4px */basis-2flex-basis: 0.5rem; /* 8px */basis-3flex-basis: 0.75rem; /* 12px */basis-4flex-basis: 1rem; /* 16px */basis-5flex-basis: 1.2…

docker-comopse容器因依懒关系无启动解决方法

1、确认出影响项目开机自启的容器 通docker logs -f 确认容器是否正常docker restart 重启容器,如果项目正常,把异常容器加入rc.local中,待开机一定时间后,重启此容器。 2、在rc.local中添加延时重启对应容器 #vim /etc/rc.loc…

STC8增强型单片机进阶开发--LED呼吸灯(PWM)

知不足而奋进 望远山而前行 文章目录 目录 文章目录 前言 目标 内容 PWM基础概念 STC8H芯片 PWMA应用 PWM配置详解 周期 占空比 模式 使能PWM 引脚配置 EAXSFR扩展寄存器 总结 前言 学习PWM(脉宽调制)是探索数字信号转模拟信号的重要一步,尤…

ad18学习笔记21:焊盘设置Paste Mask Expansion(锡膏层延伸)

在pcb上放置焊盘的时候,可以对焊盘进行设置,可以用默认的规则,可以用自定义的规则,网上很少看到自定义的规则怎么用。 参考了官方的说明文档,我只是稍微补充了一下 paste mask与solder mask有哪些区别_paste mask与s…

文件上传之使用一个属性接收多个文件

在开发过程中&#xff0c;可能遇到这样的业务&#xff1a;文件上传时个数不定&#xff0c;这样我们不能枚举出所有的文件name&#xff0c;这种情况下我们可以使用一个name将所有的文件接收下来&#xff1b; html代码 <!DOCTYPE html> <html lang"en"> …

终于更新了!时隔一年niushop多商户b2b2c的新补丁v5.0.2终于发布了,一起看看有啥新变化

注意这是最新版的V5.02_多商户V5.0.2版本更新说明 瞧瞧更新了什么内容&#xff0c; 优化功能 优化手机号、身份证等常用验证规则&#xff0c;全局化处理优化商品列表接口查询速度 修复功能修复系统内部分图片上传功能调用接口跨端口问题修复总后台和商家后台订单管理搜索标签在…

Ubuntu上安装Conda步骤

按照官方文档下载并安装miniconda脚本 https://docs.anaconda.com/free/miniconda/ mkdir -p ~/miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda…

一文彻底讲透 PyTorch

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 汇总合集…

JQC-3FF-S-Z 继电器模块使用(arduino)

前言 继电器模块可以控制电流的接通和非接通状态&#xff0c;和开关一样。实际上是用小电流去控制大电流运作的一种“自动开关” 本文只是简单使用继电器模块做一个 led 点亮和熄灭的案例&#xff0c;结合案例可以和 nodemcu 等板子结合做出远程控制开关。 材料准备 杜邦线…

无限可能LangChain——构建一个简单的LLM应用程序

在本快速入门中&#xff0c;我们将向您展示如何构建一个简单的LLM应用程序。该应用程序将文本从英语翻译成另一种语言。这是一个相对简单的LLM应用程序——它只是一个LLM调用加上一些提示。尽管如此&#xff0c;这仍然是开始使用LangChain的好方法——只需一些提示和一个LLM调用…

小波相干性显著性检验(MATLAB R2018A)

交叉小波常被用于检测不同信号之间的相关性&#xff0c;其在时频域建立了不同信号之间的联系。对于两个时域信号&#xff0c;其交叉小波变换和交叉小波尺度谱如下&#xff1a; 以轴承振动信号为例&#xff0c;利用正常轴承与故障轴承的振动信号、故障轴承和故障轴承的振动信号分…

C编程惯用法:深入剖析与实战指南

C编程惯用法&#xff1a;深入剖析与实战指南 在C语言编程的浩瀚海洋中&#xff0c;掌握一些惯用法对于提升代码质量、增强可读性以及降低出错率至关重要。本文将从四个方面、五个方面、六个方面和七个方面&#xff0c;详细剖析C编程中的惯用法&#xff0c;帮助您更好地理解和应…

Java开发-面试题-0002-ArrayList 和 LinkedList的区别

Java开发-面试题-0002-ArrayList 和 LinkedList的区别 更多内容欢迎关注我(持续更新中,欢迎Star✨) Github:CodeZeng1998/Java-Developer-Work-Note 技术公众号:CodeZeng1998(纯纯技术文) 生活公众号:好锅(Life is more than code) CSDN: CodeZeng1998 其他平台…

【sklearn | 1】sklearn 基础教程

scikit-learn&#xff08;简称 sklearn&#xff09;是一个基于 Python 的机器学习库&#xff0c;广泛应用于数据挖掘和数据分析。它提供了各种分类、回归和聚类算法&#xff0c;以及工具用于模型选择和数据预处理。本文将详细介绍 sklearn 的基本使用方法和功能。 安装 scikit-…

【JavaEE进阶】——Mybatis操作数据库(使用注解和XML方式)

目录 &#x1f6a9;三层架构 &#x1f388;JDBC操作回顾 &#x1f6a9;什么是MyBatis &#x1f6a9;MyBatis⼊⻔ &#x1f388;准备工作 &#x1f4dd;创建⼯程 &#x1f4dd;数据准备 &#x1f388;配置数据库连接字符串 &#x1f388;写持久层代码 &#x1f388;单…

用Python实现一个Lisp解析器

一、模块代码 Talk is cheap, show the code: # lisp.pyimport rescanner re.Scanner([(r\s, None),(r[^"()\s]|"[^"]*", lambda scanner, token: (NAME, token)),(r\(, lambda scanner, token: (token, token)),(r\), lambda scanner, token: (token, …

插入排序(直接插入排序、折半插入排序、希尔排序)的性能分析

目录 前言 插入排序 直接插入排序性能分析 折半插入排序性能分析 希尔排序性能分析 前言 本篇文章主要是总结插入排序的性能分析&#xff0c;具体的概念、算法、排序过程&#xff0c;我前面的文章有写&#xff0c;在这里就不再过多赘述了。 插入排序 插入排序是一种简单直…

【2024】LeetCode HOT 100——技巧

目录 1. 只出现一次的数字1.1 C++实现1.2 Python实现1.3 时空分析2. 多数元素2.1 C++实现2.2 Python实现2.3 时空分析3. 颜色分类3.1 C++实现3.2 Python实现3.3 时空分析4. 下一个排列4.1 C++实现4.2 Pyth