【原型模式】详解

一.概念

原型模式是一种创建型设计模式,它的主要思想是通过复制现有对象来创建新对象,而不是通过实例化一个类来创建。在原型模式中,我们称被复制的对象为原型(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 充当原型管理器。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【OpenHarmony】TypeScript 语法 ③ ( 条件语句 | if else 语句 | switch case 语句 )

文章目录 一、条件语句1、if else 语句2、switch case 语句 参考文档 : <HarmonyOS第一课>ArkTS开发语言介绍 一、条件语句 1、if else 语句 TypeScript 中的 if 语句 / if else 语句 用法 , 与 JavaScript 语言中的 if 语句 / if else 语句 语法 基本相同 ; if else 语…

.gitignore 文件

一.什么是 .gitignore 文件 在任何当前工作的 Git 仓库中&#xff0c;每个文件都是这样的&#xff1a; 追踪的&#xff08;tracked&#xff09;- 这些是 Git 所知道的所有文件或目录。这些是新添加&#xff08;用 git add 添加&#xff09;和提交&#xff08;用 git commit 提…

Ubuntu 20.04安装CMake 3.22.6版本

Ubuntu 20.04通过apt安装的cmake版本是3.16.3&#xff0c;默认安装到/usr/bin/cmake路径。 $ cmake Command cmake not found, but can be installed with:sudo snap install cmake # version 3.29.3, or sudo apt install cmake # version 3.16.3-1ubuntu1.20.04.1See sna…

chatgpt之api的调用问题

1.调用api过程中&#xff0c;出现如下报错内容 先写一个测试样例 import openaiopenai.api_key "OPEN_AI_KEY" openai.api_base"OPEN_AI_BASE_URL" # 是否需要base根据自己所在地区和key情况进行completion openai.ChatCompletion.create(model"g…

【PingPong_注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

C++ | Leetcode C++题解之第125题验证回文串

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isPalindrome(string s) {int n s.size();int left 0, right n - 1;while (left < right) {while (left < right && !isalnum(s[left])) {left;}while (left < right && !isalnu…

【scikit-learn010】sklearn算法模型清单实战及经验总结(已更新)

1.一直以来想写下基于scikit-learn训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架模型算法包相关技术点及经验。 3.欢迎批评指正,欢迎互三,跪谢一键…

数学建模 —— 灰色系统(4)

目录 什么是灰色系统&#xff1f; 一、灰色关联分析 1.1 灰色关联分析模型 1.2 灰色关联因素和关联算子集 1.2.1 灰色关联因素 1.2.2 关联算子集 1.3 灰色关联公理与灰色关联度 1.3.1 灰色关联度 1.3.2 灰色关联度计算步骤 1.4 广义关联度 1.4.1 灰色绝对关联…

mysql表字段超过多少影响性能 mysql表多少效率会下降

一直有传言说&#xff0c;MySQL 表的数据只要超过 2000 万行&#xff0c;其性能就会下降。而本文作者用实验分析证明&#xff1a;至少在 2023 年&#xff0c;这已不再是 MySQL 表的有效软限制。 传言 互联网上有一则传言说&#xff0c;我们应该避免单个 MySQL 表中的数据超过 …

深入分析 Android Service (完)

文章目录 深入分析 Android Service (完)1. Service 的生命周期管理2. Service 的生命周期方法2.1 onCreate()2.2 onStartCommand(Intent intent, int flags, int startId)2.3 onBind(Intent intent)2.4 onUnbind(Intent intent)2.5 onRebind(Intent intent)2.6 onDestroy() 3.…

springboot 项目集成 knife4j

官方版本推荐 版本依赖 spring boot 2.3.12.RELEASE 和 knife4j 2.0.9 引入依赖 完整的pom.xml文件 <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter --> <dependency><groupId>com.github.xiaoymin</groupI…

JavaScript笔记二-JavaScript基础语法

1、标识符 命名规则 第一个字符必须是一个字母、下划线&#xff08; _ &#xff09;或一个美元符号&#xff08; $ &#xff09;。其它字符可以是字母、下划线、美元符号或数字。按照惯例&#xff0c;ECMAScript 标识符采用驼峰命名法。标识符不能是关键字和保留字符。 2、字…

CDN——内容分发网络

目录 为什么使用CDN CDN是如何工作的 类型 推模式&#xff08;Push&#xff09; 拉模式&#xff08;Pull&#xff09; 缺点 例子 内容分发网络&#xff08;CDN&#xff09;是一组在地理上广泛分布的服务器&#xff0c;它们一起工作以提供互联网内容的快速交付。通常静态…

以sqlilabs靶场为例,讲解SQL注入攻击原理【15-17关】

【less-15&#xff1a;布尔盲注】 单引号闭合 1. or (length(database())) -- 数字&#xff1a;判断数据库长度&#xff1b; 2. or (ascii(substr(database(),1,1))) -- 数字&#xff1a;获取组成数据库的字符&#xff1b; 3. or (ascii(substr((select table_nam…

机器学习学习

机器学习类型(按学习方式分):监督学习、半监督学习、无监督学习、强化学习; 通过已知标签训练集训练模型,使用模型及逆行预测、测试; 向量表示法,其中每一维对应一个特征(feature)或者称为属性,记为[x1,x2,...,xn] 特征值、特征、标签,共同完成训练集的数据填充,最…

STM32作业实现(二)串口控制led

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

基于Chan-Vese算法的图像边缘提取matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................ % 迭代更新水平集函数 err[]…

GIS Java 生成四至图

目录 前言 操作步骤&#xff1a; 1&#xff0c;求出多边形的四至点 2&#xff0c;下载地图 3&#xff0c;绘制多边形 前言 对于地图上的一个多边形地块&#xff0c;其四至图就是能够覆盖这个多边形的最小矩形&#xff0c;也就是求出这个多边形的最东点&#xff0c;最西点&…

CATIA进阶操作——创成式曲面设计入门(1)线架设计,三维点、直线、平面、曲线

目录 引出三维空间点生成三维直线三维平面三维曲线总结异形弹簧新建几何体草图编辑&#xff0c;画一条样条线进行扫掠&#xff0c;圆心和半径画出曲面上的螺旋线再次选择扫掠&#xff0c;圆心和半径 其他自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重…