李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 每日心情
  • Now
  • 系列文章
  • AI工具集
  • 论坛
  • 左邻右舍
    • 左邻右舍
    • 朋友圈
    • 游客中心
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于本站
    • 网站地图
    • 网站统计
    • 另一个网站
    • 赞助
  • 星球穿梭
  • 🚇开往
白雪成红
惟坚韧者始能遂其志
  1. 首页
  2. 后端
  3. 正文

Java设计模式-原型模式

2020年1月10日 约 1,155 字4 分钟 185 0 0
合集:Java设计模式第 6 篇 / 共 8 篇
Java›Java设计模式
  1. 1Java设计模式:状态模式
  2. 2Java设计模式:策略模式
  3. 3Java设计模式:模板方法模式
  4. 4JAVA设计模式-抽象工厂模式
  5. 5JAVA设计模式-工厂方法模式
  6. 6Java设计模式-原型模式当前
  7. 7Java设计模式-单例模式
  8. 8设计模式总结

在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效。

定义

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

结构

原型模式包含以下主要角色:

  1. 抽象原型类:规定了具体原型对象必须实现的接口。
  2. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
    Java设计模式-原型模式

    实现

    原型模式的克隆分为浅克隆和深克隆,Java中的Object类提供了浅克隆的clone()方法,具体原型类只要实现Cloneable接口就可实现对象的浅克隆,这里的Cloneable接口就是抽象原型类。

浅克隆:仅仅克隆基本类型变量,而不克隆引用类型的变量。

深克隆:既克隆基本类型变量,也克隆引用类型变量。

package com.lifengdi.designpatterns.demo.prototype;

import lombok.Data;

import java.io.*;
import java.util.Objects;

/**
 * 原型模式-浅克隆(实现Cloneable接口)
 * 原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,
 * 通过复制该原型对象来创建一个和原型相同或相似的新对象。
 * 在这里,原型实例指定了要创建的对象的种类。
 * 用这种方式创建对象非常高效,根本无须知道对象创建的细节。
 *
 * 原型模式的克隆分为浅克隆和深克隆,
 * Java 中的 Object 类提供了浅克隆的 clone() 方法,
 * 具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,
 * 这里的 Cloneable 接口就是抽象原型类。
 *
 * 浅拷贝:仅仅克隆基本类型变量,而不克隆引用类型的变量
 * 深克隆:既克隆基本类型变量,也克隆引用类型变量
 * @author 李锋镝
 * @date Create at 14:02 2019/12/13
 */
@Data
public class CloneablePrototype implements Cloneable, Serializable{

    private static final long serialVersionUID = 490320022607137415L;

    // 上文所说的浅拷贝只会克隆基本数据属性,而不会克隆引用其他对象的属性,
    // 但String对象又不属于基本属性,这又是为什么呢?
    //
    // 这是因为String对象是不可修改的对象,每次修改其实都是新建一个新的对象,
    // 而不是在原有的对象上修改,所以当修改String属性时其实是新开辟一个空间存储String对象,
    // 并把引用指向该内存,而克隆出来的对象的String属性还是指向原有的内存地址,
    // 所以String对象在浅克隆中也表现得与基本属性一样。
    private String name;

    private int age;

    private Job job;

    /**
     * 浅拷贝
     * @return Object
     * @throws CloneNotSupportedException CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    /**
     * 深克隆
     * @return CloneablePrototype
     * @throws CloneNotSupportedException CloneNotSupportedException
     */
    CloneablePrototype deepClone() throws CloneNotSupportedException {
        CloneablePrototype cloneProtoType = (CloneablePrototype)super.clone();
        Job cloneJob = (Job)cloneProtoType.getJob().clone();
        cloneProtoType.setJob(cloneJob);
        return cloneProtoType;
    }

    /**
     * 深克隆(序列化实现)
     * @return CloneablePrototype
     * @throws IOException IOException
     * @throws ClassNotFoundException ClassNotFoundException
     */
    CloneablePrototype deepCopy() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //将当前这个对象写到一个输出流当中,,因为这个对象的类实现了Serializable这个接口,所以在这个类中
        //有一个引用,这个引用如果实现了序列化,那么这个也会写到这个输出流当中
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (CloneablePrototype)ois.readObject();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CloneablePrototype that = (CloneablePrototype) o;
        return age == that.age &&
                Objects.equals(name, that.name) &&
                Objects.equals(job, that.job);
    }

    /**
     * 两个对象相等,hashcode一定相等
     * 两个对象不等,hashcode不一定不等
     * hashcode相等,两个对象不一定相等
     * hashcode不等,两个对象一定不等
     *
     * @return hashcode
     */
    @Override
    public int hashCode() {

        return Objects.hash(name, age, job);
    }
}
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
分享到

Java设计模式-原型模式

也可使用浏览器菜单中的「分享」功能

微信扫一扫分享

标签: JAVA 原型模式 设计模式
最后更新:2026年7月14日
相关文章
  • 解决IDEA2024UI卡顿问题2024年6月11日
  • 何谓重构?为何重构?2019年6月24日
  • TestNG基本注解2019年7月23日
  • MapStruct深度解析:从原理到实战,告别BeanUtil的性能与安全痛点2025年10月22日
  • SpringBoot 中内置的 49 个常用工具类2025年5月26日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 合集上一篇
合集下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

还没有评论,快来抢沙发吧~

问君能有几多愁,恰似一江春水向东流。

听点儿音乐吧 朋友~
文章目录
最新 热点 随机
最新 热点 随机
Kratos-plus v1.1.26版本更新说明 我觉得是时候公布我的导航网站了 代码是 AI 写的,生产事故谁背锅? 给主题增加了游客中心功能 祝大家中秋安康 游本昌去世
给主题增加了游客中心功能游本昌去世关于主题加载速度优化的一点儿小演进我觉得是时候公布我的导航网站了给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能WordPress缓存插件WP Fastest Cache、WP Rocket 、FlyingPress对比
这个中秋节感觉过的好累啊 给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能 为什么 K8s 在阿里能成功?| 问底中国 IT 技术演进 为什么关于香菜的评价这么两极? 西蒙学习法实战指南:6个月攻克新领域,从入门到能用的高效路径 一款节省token的利器:RTK(Rust Token Killer)
最近评论
fairy 发布于 13 小时前(10月02日) 很明显,只能处罚人,当然是人背锅。你能罚AI钱吗?能把AI辞退吗?很明显不能。
彬红茶 发布于 17 小时前(10月02日) 很全面哦~国庆快乐
彬红茶 发布于 20 小时前(10月01日) 确实可以加一下这个功能,我最近就改了,评论区加了个等级,游客中心实属无能为力 :78:
皮皮社长 发布于 1 天前(10月01日) 快看快看,我皮皮社长上榜了~ :2:
皮皮社长 发布于 1 天前(10月01日) 我直接把喜欢的网站放到友链中就好了,简单明了~ :40:
标签聚合
ElasticSearch JAVA SQL AI 日常 架构 AI编程 K8s 分布式 Spring SpringBoot IDEA Theme Redis MySQL Claude 数据库 多线程 WordPress JVM
友情链接
  • 懋和道人
  • 哥斯拉
  • 皮皮社
  • lijie blog
  • 韩情脉脉
  • 蜗牛工作室
  • 志文工作室
  • 老张博客
  • 彬红茶日记
  • 瓦匠个人小站
  • Serendipity
  • 林羽凡
  • Honesty
  • 搬砖日记
  • Mr.Sun的博客
  • 九仞之行
  • 若梦博客
  • 知向前端
  • sssr7844的博客
  • 韩小韩博客

COPYRIGHT © 2016-2026 lifengdi.com. ALL RIGHTS RESERVED.

lifengdi.com

Domain age badge for lifengdi.com

Theme Kratos-plus By Dylan Li

津ICP备2024022503号-3

京公网安备11011502039375号