Java基础:设计模式之原型模式

devtools/2024/9/22 19:40:58/

原型模式是一种创建型设计模式,它允许我们通过复制现有的对象来创建新的对象,而不是每次都通过构造函数新建。这种模式适用于那些创建新对象成本较高或者构造过程复杂的情况。在原型模式中,一个对象通过实现Cloneable接口并重写其clone()方法来作为原型。当需要创建新对象时,客户端代码请求原型对象克隆自身,返回一个与原对象状态相同的新对象。

结构与参与者
  1. Prototype(原型): 这是一个接口或抽象类,声明了克隆自己的方法(通常是clone())。所有具体原型类都必须实现这个接口或继承这个抽象类。

  2. ConcretePrototype(具体原型): 实现了Prototype接口或继承了抽象原型类的具体类。它们实现了clone()方法以创建自己的副本(克隆)。

工作流程
  1. 客户端 需要新对象时,不是直接调用构造函数创建,而是请求一个已存在的原型对象克隆自身。

  2. 原型对象 通过实现Cloneable接口,并重写Object类中的clone()方法来提供克隆能力。clone()方法通常会创建一个新的对象,并将当前对象的状态(属性值)复制到新对象中。

  3. 新对象 作为原型对象的副本被返回给客户端,新对象与原型对象状态相同但不共享任何引用数据(除非在深复制中特殊处理)。

适用场景
  1. 对象创建成本高:如果创建一个对象需要大量计算、消耗大量资源(如数据库查询、网络通信、复杂的初始化逻辑等),原型模式可以快速复制已有对象,避免重复高昂的创建成本。

  2. 对象初始化过程复杂:当对象的初始化涉及许多步骤、依赖关系或者权限控制时,使用原型模式可简化创建过程,只需克隆已配置好的原型即可。

  3. 需要大量相似对象:在系统中需要大量具有相同或相似属性的对象,但又不希望引入额外的开销(如频繁的构造函数调用),可以通过复制少量原型对象来生成大量实例。

  4. 保护性拷贝:当一个对象需要提供给多个调用者使用,且调用者可能需要修改对象的属性,通过原型模式可以为每个调用者提供对象的一个独立副本,防止相互干扰。

示例说明
java">import java.util.Date;// 原型接口
interface Prototype {Prototype clone();
}// 具体原型类:员工信息
class Employee implements Prototype {private String name;private int id;private Date hireDate;// 构造函数和常规setter/getter省略...@Overridepublic Prototype clone() {try {return (Prototype) super.clone(); // 调用Object的clone方法进行浅复制} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}
}// 客户端代码
public class PrototypeDemo {public static void main(String[] args) {// 创建一个原型员工对象Employee original = new Employee("Alice", 1, new Date());// 使用原型模式克隆出新员工Employee cloned = original.clone();// 改变克隆员工的信息cloned.setName("Bob");System.out.println("Original employee: " + original.getName());System.out.println("Cloned employee: " + cloned.getName());}
}

在这个例子中,Employee类实现了Prototype接口并提供了clone()方法。客户端代码通过调用original.clone()快速创建了一个与原对象状态相同的cloned对象。之后修改cloned对象的名称不会影响到原始对象。

存在的问题
  1. 深拷贝与浅拷贝问题:Java中的clone()方法默认执行浅拷贝,即只复制对象本身及其基本类型字段,对于引用类型字段,只是复制了引用,导致原对象和克隆对象共享同一份引用所指向的数据。在某些场景下,这可能导致意外的数据修改。若需完全复制引用类型字段的内容(深拷贝),需要在clone()方法中手动复制这些字段。

  2. Cloneable接口不强制约束:Java的Cloneable接口没有定义任何方法,只是一个标记接口,表明该类支持被克隆。但如果不重写Objectclone()方法并抛出CloneNotSupportedException,则直接调用clone()会抛出异常。这种设计可能导致不符合预期的行为,需要开发者明确了解并正确实现克隆逻辑。

  3. 代码侵入性:为了实现原型模式,需要修改类以实现Cloneable接口并重写clone()方法,这可能对已有代码产生一定侵入性,特别是对于那些原本不需要支持克隆的类。

  4. 错误使用可能导致内存浪费:如果频繁地克隆大对象或含有大量数据的集合,且实际场景并不需要这么多对象副本,可能会造成不必要的内存消耗。

  5. 线程安全问题:在多线程环境中,如果没有正确同步原型对象的访问和克隆过程,可能会导致数据不一致或并发问题。

综上所述,虽然原型模式在特定场景下能有效提高对象创建效率,但使用时需谨慎权衡其带来的复杂性、潜在风险以及对系统设计的影响。在实际应用中,可能还需要结合工厂方法、单例模式等其他创建型模式来优化对象创建过程。


http://www.ppmy.cn/devtools/16637.html

相关文章

ds18b20温度传感器驱动程序

ds18b20驱动程序 有了之前延时的方法,那么实现一个单总线数据传输的传感器驱动程序就非常简单了。下面我们套用杂项驱动框架来编写ds18b20驱动程序。 实现需要明确的是:**ds18b20驱动的本质是通过2440的gpio,通过给定的时序对ds18b20的读写数…

上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 如果软件开发好了之后,下面就是实施和部署。对于树莓派4b来说,部署其实就是烧录卡和拷贝文件。之前我们烧录卡,…

图神经网络 | 混合神经网络模型GCTN地铁客流预测

随着城市人口的不断增加,城市交通也在迅速扩张,这对城市的可持续发展提出了新的挑战。与私家车相比,城市轨道交通可以减少与交通相关的能源消耗、出行成本、交通拥堵和环境污染。同时,研究表明,在城市轨道交通强度较高的城市,汽车保有量的增长相对较慢。因此,地铁、公交…

vue+springboot项目的登录验证码(JAVA自带)

后台springboot CaptureController package com.example.controller;import com.example.common.Result; import com.example.service.AuthCodeService; import com.example.utils.CodeUtils; import lombok.SneakyThrows; import org.apache.ibatis.annotations.Param; impo…

浅谈菊风实时音视频 (RTC)与实时操作系统 (RTOS) 在智能硬件领域应用

近年来,菊风通过实时音视频赋能智能手表、智能门禁、智能门锁/门铃、智能眼镜等数十种智能硬件,与一众合作伙伴共同探索在IoT智能硬件领域的不同场景应用,积累了丰富的实践经验。在智能硬件中,RTOS因其轻量化的系统内核&#xff0…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 一、简单介绍 二、简单进行人脸训练与识别 1、LBPH…

开源向量数据库比较:Chroma, Milvus, Faiss,Weaviate

语义搜索和检索增强生成(RAG)正在彻底改变我们的在线交互方式。实现这些突破性进展的支柱就是向量数据库。选择正确的向量数据库能是一项艰巨的任务。本文为你提供四个重要的开源向量数据库之间的全面比较,希望你能够选择出最符合自己特定需求的数据库。 什么是向量…

PostgreSQL的学习心得和知识总结(一百三十九)|深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…