原型模式的实现

1. 引言

1.1 背景

在实际编程中,有时需要频繁创建多个相似但稍有不同的对象。如果采用传统的对象创建方式,容易造成代码冗余,对象重复初始化操作也可能带来大量的的资源消耗(如时间、内存等)。这样不仅降低了灵活性,导致难以适应状态的变化,还降低了代码的可扩展性。

public class Demo {
    public static void main(String[] args) {
        // 创建原型对象
        A a = getA();
        
        B b = new B();
        b.setParam(a.getParam());        
         // ...
        System.out.println("B: " + b);        C c = new C();
        c.setPartam(b.getPartam());
        // ...
        System.out.println("C: " + c);
    }
}

在面向对象编程的世界里,为了帮助开发者写出更高质量、更易于维护代码的一套解决方案。针对此类问题的,提供了原型模式。原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有实例来创建新对象,避免了重复的初始化操作。适用于对象的创建过程昂贵、复杂或者外部变化频繁的情况。在需要快速创建复杂对象副本的业务中,可以通过原型模式避免每次都重新初始化所带来的开销。


1.2 目的

本文将详细介绍原型模式的基本概念、实现步骤。通过本篇文章,你将能够理解原型模式的工作原理,并学会如何在实际项目中有效地利用它。


2. 何为原型模式?

一句话概括,就是使用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。

2.1 原型模式的目的

原型模式的核心目的是通过复制现有的对象来创建新对象,从而避免昂贵的对象创建过程。这在某些场景下尤为有用,例如:

创建成本高:对象的创建成本(如时间、资源)非常高。
复杂对象:对象有很多复杂的结构,初始化过程复杂且耗时。
需要创建多个相似对象:频繁需要创建多个相似但稍有不同的对象。

2.2 原型模式适合的场景

  1. 对象重复创建:在需要频繁创建类似对象并减少初始化开销的场景下。
  2. 对象初始化复杂:对象的创建过程涉及大量计算或资源分配,通过克隆可以避免这些开销。
  3. 不同配置的对象:需要创建多个配置类似但具体值不同的对象时,通过克隆基准对象进行调整。

2.3 为什么不直接使用Clone方法复制类?

直接在需要复制的类中调用 clone 方法当然是简单的实现方式,但也有一些局限性:

  1. 破坏封装:直接调用 clone 方法可能会破坏类的封装,导致类内部的实现细节暴露。
  2. 不支持多态性:使用接口或抽象类,有助于处理多个不同类型的对象。用户可以通过接口调用 clone 方法,从而实现多态性,而直接调用 clone 方法无法做到这一点。
  3. 可能需要深拷贝:有些对象需要深拷贝(对引用类型的成员进行拷贝),直接的 clone 方法可能无法满足这一需求。通过接口或抽象类可以更灵活地实现深拷贝逻辑。

2.4 浅拷贝和深拷贝&原型模式的关联

在讨论原型模式时,深拷贝和浅拷贝是两个非常重要的概念。它们与原型模式密切相关,因为原型模式涉及到对象的复制,而对象的复制又可以分为浅拷贝和深拷贝两种方式。

何为浅拷贝?
浅拷贝(Shallow Copy)在对象复制过程中,只复制对象的基本数据类型字段,对于引用类型字段,只复制引用,不复制引用对象本身。这意味着浅拷贝后的新对象与原对象共享相同的引用对象。在 Java 中,可以使用 Object 类的 clone 方法来实现浅拷贝。默认的 clone 方法进行的是浅拷贝:

public class ShallowCopyExample implements Cloneable {private int value;private int[] array;public ShallowCopyExample(int value, int[] array) {this.value = value;this.array = array;}@Overrideprotected ShallowCopyExample clone() {try {return (ShallowCopyExample) super.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}// Getters and setters...public static void main(String[] args) {int[] array = {1, 2, 3};ShallowCopyExample original = new ShallowCopyExample(42, array);ShallowCopyExample cloned = original.clone();System.out.println("初始的数组: " + original.getArray()[0]); // 1System.out.println("克隆对象的数组: " + cloned.getArray()[0]); // 1// 修改克隆对象的数组cloned.getArray()[0] = 99;System.out.println("初始的数组: " + original.getArray()[0]); // 99System.out.println("克隆对象的数组: " + cloned.getArray()[0]); // 99}
}

如上所示,修改克隆对象的数组会影响原始对象的数组,这是因为它们共享相同的引用。

何为深拷贝?
深拷贝(Deep Copy)在对象复制过程中,除了复制对象的基本数据类型字段,还递归复制引用类型字段所引用的对象。这意

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

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

相关文章

挑战与成长:面对他人成就引发的焦虑与迷茫

挑战与成长:面对他人成就引发的焦虑与迷茫 对于追求知识和技能的人来说,看到他人做出自己尚未达到的成就确实会带来焦虑感。这种焦虑常常源于对自己能力的质疑和对未来的不确定性。 在我的学习和发展过程中,有时确实会看到其他模型或系统能…

实操Nginx+Tomcat多实例部署,实现负载均衡和动静分离

192.168.10.10 192.168.10.20 192.168.10.30 location ~ \.jsp$ {proxy_pass http://192.168.10.50:8080;} location ~ \.(jsp|html)$ {root /usr/share/nginx/html;}192.168.10.40和192.168.10.50用脚本完成搭建此处安装附上脚本: #!/bin/bash# 定义变量 JDK_PACKA…

等保测评——云计算安全扩展(云计算关键技术)

虚拟化技术: 虚拟化是云计算的核心技术之一,它为云计算服务提供基础架构层面的支撑,是ICT(信息通信技术)服务快速走向云计算的最主要驱动力。虚拟化作为云计算的重要组成部分,最大的好处是能增强系统的弹性和灵活性&a…

【微服务网关——Websocket代理】

1.Websocket协议与原理 1.1 连接建立协议 1.1.1 客户端发起连接请求 客户端通过 HTTP 请求发起 WebSocket 连接。以下是一个 WebSocket 握手请求的例子: GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key…

题目:只通过+1和×2两种操作,最少几次能把0变成20240701?

偶然在网上看到了一个题目,看了看视频和评论,感觉挺有意思,记录一下。 只通过1和2两种操作,最少几次能把0变成20240701?_哔哩哔哩_bilibili 题目:只通过1和2两种操作,最少几次能把0变成202407…

Python面试宝典第3题:石子游戏

题目 Alice 和 Bob 用几堆石子在做游戏:一共有偶数堆石子,排成一行;每堆都有正整数颗石子,数目为 piles[i] 。游戏以谁手中的石子最多来决出胜负,石子的总数是奇数 ,所以没有平局。 Alice 和 Bob 轮流进行&…

CV01_相机成像原理与坐标系之间的转换

目录 0.引言:小孔成像->映射表达式 1. 相机自身的运动如何表征?->外参矩阵E 1.1 旋转 1.2 平移 2. 如何投影到“像平面”?->内参矩阵K 2.1 图像平面坐标转换为像素坐标系 3. 三维到二维的维度是如何丢失的?…

LVS-负载均衡

目录 一、概念 二、LVS工作原理 1. ipvs/ipvsadm 2.名词: 三、常用命令 四、工作模式 1.NAT地址转换模式 (1)工作流程 (2)特点 (3)实验过程 a.环境准备: b.修改测试机的…

UE5 动画蓝图

文章目录 一、State Machines二、Blend Spaces三、Aim Offset四、Montage 初步介绍 Unreal Engine 5 Tutorial - Animation Blueprint Part 1: State Machines (youtube.com) Unreal Engine 5 Tutorial - Animation Blueprint Part 2: Blend Spaces (youtube.com) Unreal Engi…

非静压模型SWASH学习(8)——三维孤立波在锥形岛屿上的爬坡过程(Runup of solitary waves on a conical island)

三维孤立波在锥形岛屿上的爬坡过程(Runup of solitary waves on a conical island) 算例简介模型配置网格及参数设置网格与地形初始条件与边界条件数值求解方法输出设置模拟时间 波浪(孤立波)入射边界的时间序列.bnd文件模拟结果注…

HTML5 SVG: 探索矢量图形的新纪元

HTML5 SVG: 探索矢量图形的新纪元 引言 HTML5,作为现代网页开发的核心技术之一,极大地推动了网页内容的丰富性和交互性。在HTML5的众多特性中,SVG(可缩放矢量图形)发挥着重要作用,它允许开发者创建复杂、响应式的矢量图形,这些图形在任何分辨率下都能保持清晰。本文将…

服务器推送有几种方式,分别有什么优缺点

服务器推送主要有以下几种方式: 长轮询(Long Polling): 优点: 相对简单易实现。能够在一定程度上减少无效的请求,降低服务器资源消耗。 缺点: 仍然存在一定的延迟。如果连接意外中断&#xff…

[吃瓜教程]南瓜书第4章决策树

1.决策树的算法原理 从逻辑角度,条件判断语句的组合;从几何角度,根据某种准则划分特征空间; 是一种分治的思想,其最终目的是将样本约分约纯,而划分的核心是在条件的选择或者说是**特征空间的划分标准 ** …

Mamba项目实战-Ubuntu

注:演示环境需要一个可用的cuda环境,可执行两个命令进行验证 1.nvidia-smi 2.nvcc -V 若出现正确输出,可继续博客以下的操作步骤,否则请确认是否已经安装或已配置环境变量,若未安装则转到博客:深度学习项…

mac安装达梦数据库

参考:mac安装达梦数据库​​​​​​ 实践如下: 1、下载达梦Docker镜像文件 同参考链接 2、导入镜像 镜像可以随便放在某个目录,相当于安装包,导入后就没有作用了。 查找达梦镜像名称:dm8_20240613_rev229704_x86…

第1章 人工智能的基础概念与应用导论

亲爱的读者朋友们,你们好!欢迎来到这个充满神奇与奥秘的人工智能世界。我知道,对于很多人来说,人工智能(AI)可能是个既神秘又高大上的词汇,仿佛遥不可及,只存在于科幻电影或者顶级科…

Figma-ui设计学习APP Store

Figma汉化:Figma 中文社区_插件组件库,软件汉化教程 - Figma.Cool 选择Chorme汉化版离线包 插件安装: 打开浏览器安装扩展,解压加载进去即可。 打开标尺,设置左右内边距参考线(左21 右356),wi…

Java使用分布式实现数据库读写分离

配置主从复制:在MySQL中,可以通过配置主从复制来实现数据同步。将一个节点作为主节点(Master),其他节点作为从节点(Slave)。当主节点上的数据发生变化时,自动将变更内容同步到所有从…

JS面试题6——深拷贝和浅拷贝

它们都是用来复制的 1. 浅拷贝(只复制引用,而未复制真正的值) /* 简单赋值 */ var arr1 [a, b, c, d]; var arr2 arr1; /* Object.assign实现的也是浅拷贝 */ var obj1 {a:1, b:2} var obj2 Object.assign(obj1); 2. 深拷贝(是…

C++ 预处理器定义

目录 一、什么是预处理器定义 二、常见用法 1. 条件编译 2. 宏定义 3. 防止重复包含 4. 动态链接库的导入导出 5、如何设置预处理器定义 一、什么是预处理器定义 预处理器定义(Preprocessor Definitions)在C和C编程中用于在编译过程中进行文本替换…