【创建型模式】原型模式

一、原型模式概述

        原型(Prototype)模式的定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。(对象创建型)

  •  工作原理
    • 将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程。
    • 创建新对象(也称克隆对象)的工厂就是原型类自身,工厂方法由负责复制原型对象的克隆方法来实现。
    • 通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,每个克隆对象都是独立的。
    • 通过不同的方式对克隆对象进行修改以后,可以得到一系列相似但不完全相同的对象。
  • 浅克隆与深克隆
    • 浅克隆:当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。
    • ​深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将被复制。
  • 原型管理器
    • 将多个原型对象存储在一个集合中提供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象,如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得。
  • 原型模式的优缺点
    • 优点
      • 1.简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率;
      • 2.扩展性好;
      • 3.提供了简化的创建结构,原型模式中的产品的复制时通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品;
      • 4.可以使用深克隆的方式保存对象的状态,以便在需要的时候使用,可辅助实现撤销操作。
    • 缺点
      • 1.需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当已有对象的类进行改造时们需要修改源代码,违背了开闭原则;
      • 2.在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应得类都必须支持深克隆,实现起来可能会比较麻烦。
  • 适用环境
    • 1.创建新对象成本比较大,新对象可以通过复制已有对象来获得,如果相似对象,则可以对其成员变量稍作修改;
    • 2.系统要保存对象得状态,而对象得状态变化很小;
    • 3.需要便面使用分层次得工厂类来创建分层次得对象;
    • 4.ctrl+c->ctrl+v。

二、代码实现

        原型模式包含三个角色:

  • 访问类(客户类):提出创建对象的请求,使用具体原型类中的 clone() 方法来复制新的对象。
  • 抽象原型(Prototype)角色:此角色定义了的具体原型类所需的实现的方法。也就是定义一个文件,说明一下它有被克隆复制的功能。
  • 具体原型(Concrete Prototype)角色:实现抽象原型角色的克隆接口。就是我们的文件实现了可以被复制的功能。

        我们会发现其实原型模式的核心就是Prototype(抽象原型),他需要继承Cloneable接口,并且重写Object类中的clone方法才能有复制粘贴的功能。

2.1 demo

        2.1.1 抽象原型角色
package prototype.demo;
//抽象原型角色
public interface Prototype {public Prototype clone();
}
        2.1.2 具体原型角色
package prototype.demo;
//具体原型角色
public class ConcretePrototype implements Prototype{private int dataInt=1;private A dataA=new A();public String toString() {return "ConcretePrototype"+"["+",dataInt"+dataInt+",dataA_address="+dataA+",dataA="+dataA.getChar_a()+"]";}public int getDataInt() {return dataInt;}public void setDataInt(int dataInt) {this.dataInt = dataInt;}public A getDataA() {return dataA;}public void setDataA(A dataA) {this.dataA = dataA;}//克隆方法 shallowpublic Prototype clone() {ConcretePrototype copy=new ConcretePrototype();copy.setDataInt(this.getDataInt());copy.setDataA(this.getDataA());return copy;}//克隆方法 deeppublic Prototype clone2() {ConcretePrototype copy=new ConcretePrototype();copy.setDataInt(this.getDataInt());A ta=new A();ta.setChar_a(this.getDataA().getChar_a());copy.setDataA(this.getDataA());return copy;}}
package prototype.demo;
//封装的方法
public class A {char char_a;public char getChar_a() {return char_a;}public void setChar_a(char char_a) {this.char_a = char_a;}public A(char char_a) {super();this.char_a=char_a;}public A() {this.char_a='a';}
}
        2.1.3 main方法实现原型模式(Client)
package prototype.demo;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根/*ConcretePrototype p=new ConcretePrototype();ConcretePrototype copy=(ConcretePrototype) p.clone();ConcretePrototype copy2=(ConcretePrototype) p.clone();System.out.println(p.toString());System.out.println(copy.toString());System.out.println(copy2.toString());copy.setDataInt(2);A a=new A('b');copy.setDataA(a);System.out.println("-------------------------------");System.out.println(p.toString());System.out.println(copy.toString());System.out.println(copy2.toString());*/ConcretePrototype p=new ConcretePrototype();ConcretePrototype copy=(ConcretePrototype) p.clone2();ConcretePrototype copy2=(ConcretePrototype) p.clone2();System.out.println(p.toString());System.out.println(copy.toString());System.out.println(copy2.toString());copy.setDataInt(2);A a=new A('b');copy.setDataA(a);System.out.println("-------------------------------");System.out.println(p.toString());System.out.println(copy.toString());System.out.println(copy2.toString());}}
        2.4 UML图

2.2 浅克隆

        2.2.1 抽象原型角色

        java.io.Serializable这个接口。

        2.2.2 具体原型角色
package prototype.deepclone;import java.io.Serializable;
//实现了Serializable这个接口
public class Attachment implements Serializable{private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void download() {System.out.println("下载附件,文件名为:"+name);}
}
package prototype.shallowclone;public class WeeklyLog implements Cloneable{//简化设计,定义一个附件private Attachment attachment;private String name;private String date;private String content;public Attachment getAttachment() {return attachment;}public void setAttachment(Attachment attachment) {this.attachment = attachment;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}//使用clone()方法实现浅克隆@Overrideprotected WeeklyLog clone(){// TODO 自动生成的方法存根try {return (WeeklyLog)super.clone();} catch (CloneNotSupportedException e) {// TODO 自动生成的 catch 块e.printStackTrace();return null;}	}}
        2.2.3 Client
package prototype.shallowclone;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根WeeklyLog obj=new WeeklyLog();Attachment att=new Attachment();att.setName("obj");obj.setAttachment(att);WeeklyLog copy=obj.clone();obj.getAttachment().download();copy.getAttachment().download();}}

2.3 深克隆

        2.2.1 抽象原型角色

        java.io.Serializable这个接口。

        2.2.2 具体原型角色
package prototype.deepclone;import java.io.Serializable;
//实现了Serializable这个接口
public class Attachment implements Serializable{private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void download() {System.out.println("下载附件,文件名为:"+name);}
}
package prototype.deepclone;import java.io.*;public class WeeklyLog implements Serializable{//简化设计,定义一个附件private Attachment attachment;private String name;private String date;private String content;public Attachment getAttachment() {return attachment;}public void setAttachment(Attachment attachment) {this.attachment = attachment;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}//使用序列化技术实现克隆protected WeeklyLog deepClone() throws IOException,ClassNotFoundException{// TODO 自动生成的方法存根//将对象写入流中ByteArrayOutputStream bao=new ByteArrayOutputStream();ObjectOutputStream oos=new ObjectOutputStream(bao);oos.writeObject(this);//将对象从流中取出ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());ObjectInputStream ois=new ObjectInputStream(bis);return (WeeklyLog)ois.readObject();}}
        2.2.3 Client
package prototype.deepclone;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根WeeklyLog log_previous,log_new=null;log_previous=new WeeklyLog();//创建原型对象Attachment attachment=new Attachment();//创建附件对象attachment.setName("aaa");log_previous.setAttachment(attachment);//将附件添加到周报中try {log_new=log_previous.deepClone();//调用深克隆方法}catch(Exception e) {System.out.println("克隆失败!");}//比较周报System.out.println("周报是否相同?"+(log_previous==log_new));//比较附件System.out.println("附件是否相同?"+(log_previous.getAttachment()==log_new.getAttachment()));log_previous.getAttachment().download();log_new.getAttachment().download();}}

三、代码结构图

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

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

相关文章

吴恩达深度学习笔记:深度学习的 实践层面 (Practical aspects of Deep Learning)1.4-1.5

目录 第一门课:第二门课 改善深层神经网络:超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第一周:深度学习的 实践层面 (Practical aspects of Deep Learning)…

Vue接收接口返回的mp3格式数据并支持在页面播放音频

一、背景简介 在实际工作中需要开发一个转音频工具,并且能够在平台页面点击播放按钮播放音频 二、相关知识介绍 2.1 JS内置对象Blob Blob对象通常用于处理大量的二进制数据,可以读取/写入/操作文件、音视频等二进制数据流。Blob表示了一段不可变的二…

【PCL】教程alignment_prerejective.cpp 刚性物体的鲁棒位姿估计

The viewer window provides interactive commands; for help, press h or H from within the window. > Loading V:\learn\PCL\pcl\examples\test\chef.pcd [PCLVisualizer::setUseVbos] Has no effect when OpenGL version is 鈮?2 [done, 327.147 ms : 5092 points] Ava…

AI大模型量化格式介绍(GPTQ,GGML,GGUF,FP16/INT8/INT4)

在 HuggingFace 上下载模型时,经常会看到模型的名称会带有fp16、GPTQ,GGML等字样,对不熟悉模型量化的同学来说,这些字样可能会让人摸不着头脑,我开始也是一头雾水,后来通过查阅资料,总算有了一些…

DFS之剪枝(上交考研题目--正方形数组的数目)

题目 给定一个非负整数数组 A A A,如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。 返回 A A A 的正方形排列的数目。 两个排列 A 1 A1 A1 和 A 2 A2 A2 不同的充要条件是存在某个索引 i i i,使得 A 1 [ i …

测试一下 Meta Llama3-70b-Instruct-q8

测试一下 Meta Llama3-70b-Instruct-q8 0. 引言1. 测试 Meta Llama3-70b-Instruct-q8 0. 引言 今天,Meta 正式介绍Meta Llama 3,Meta 开源大型语言模型的下一代产品。 这次发布包括具有80亿(8B)和700亿(70B&#xff0…

指纹浏览器如何高效帮助TikTok账号矩阵搭建?

TikTok的账号矩阵,可能听起来还比较陌生,但随着TikTok业务已经成为吃手可热的跨境业务,TikTok多账号矩阵已成为流行策略。但它有什么优点呢?操作多个帐户会导致被禁止吗?如何有效地建立账户矩阵开展业务?这…

CANfestival 主机进入预操作态(preOperational)自动发送复位节点指令。

核心是iam_a_slave ,这个是字典生产的时候自动生成的。

【Flutter】多语言方案一:flutter_localizations 与 GetX 配合版

系列文章目录 多语言方案:flutter_localizations 与 GetX 配合版,好处:命令行生成多语言字符串的引用常量类,缺点:切换语言以后,主界面需要手动触发setState,重绘将最新的Locale数据设置给GetM…

使用LangChain和Llama-Index实现多重检索RAG

大家好,在信息检索的世界里,查询扩展技术正引领着一场效率革命。本文将介绍这一技术的核心多查询检索,以及其是如何在LangChain和Llama-Index中得到应用的。 1.查询扩展 查询扩展是一种信息检索技术,通过在原始查询的基础上增加…

基于Springboot的简历系统

基于SpringbootVue的简历系统的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页 简历模板 招聘会 求职论坛 系统公告 后台登录 后台首页 用户管理 简历模板 模板…

uniapp中scroll-view初始化的时候 无法横向滚动到某个为止

项目需求 实现日历&#xff08;13天&#xff09;默认高亮第六天 并定位到第六 左边右边各六天&#xff08;可以滑动&#xff09; 直接上代码 <template><scroll-view class"scroll-X":show-scrollbar"true" :scroll-x"scrollable":…

OpenHarmony网络组件-Mars

项目简介 Mars 是一个跨平台的网络组件&#xff0c;包括主要用于网络请求中的长连接&#xff0c;短连接&#xff0c;是基于 socket 层的解决方案&#xff0c;在网络调优方面有更好的可控性&#xff0c;暂不支持HTTP协议。 Mars 极大的方便了开发者的开发效率。 效果演示 编译…

产废端实时音视频监控系统在运输车辆驾驶室中的应用

实时音视频监控系统可通过在运输车辆驾驶室安装音视频摄录设备&#xff0c;实现将运输车辆内部及周围环境音视频数据通过移动网络实时回传指挥中心的功能。 前端摄录设备主要负责采集车内外的视音频信息&#xff0c;为了保障车辆及运输人员 的安全&#xff0c;应合理选择摄录设…

【多线程】定时器 | 线程池 | 实现MyTimer | 实现MyThreadPoll | 工厂模式 | 构造方法 | 参数种类

文章目录 定时器&线程池一、定时器1.标准库中的定时器2.实现定时器 二、线程池1.线程池的概念线程池&#xff1a; 2.标准库当中的线程池工厂模式 Executors 创建线程池1.自适应线程池2.固定数量线程池3.只有单个线程的线程池4.设定延迟时间后执行命令的线程池 ThreadPoolEx…

BNB链融合

BNB Chain融合 BNB Chain目前有BNB智能链&#xff08;BSC&#xff09;&#xff0c;BNB信标链 BNB信标链&#xff1a;用作质押和投票的治理层&#xff0c;采用BEP-2代币标准BNB智能链(BSC)&#xff1a;用作EVM兼容层&#xff0c;提供DApp、DeFi服务、共识层、多链支持和其他Web3…

阿里云服务器上配置Docker 以及常用命令讲解

目录 一、认识docer二、在阿里云服务器上配置Docker三、底层原理4、常用命令&#xff08;1&#xff09;Docker中常见镜像命令&#xff08;2&#xff09;Docker中常见容器命令&#xff08;3&#xff09;日志查看命令&#xff08;4&#xff09;进入容器的命令与拷贝命令 一、认识…

【目标检测】Focal Loss

Focal Loss用来解决正负样本不平衡问题&#xff0c;并提升训练过程对困难样本的关注。 在一阶段目标检测算法中&#xff0c;以YOLO v3为例&#xff0c;计算置信度损失&#xff08;图中第3、4项&#xff09;时有目标的点少&#xff0c;无目标的点多&#xff0c;两者可能相差百倍…

【1524】java投票管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 投票管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

Rust入门-所有权与借用

一、为什么、是什么、怎么用 1、为什么Rust要提出一个所有权和借用的概念 所有的程序都必须和计算机内存打交道&#xff0c;如何从内存中申请空间来存放程序的运行内容&#xff0c;如何在不需要的时候释放这些空间&#xff0c;成为所有编程语言设计的难点之一。 主要分为三种…