千家信息网

Java原型模式的示例分析

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,这篇文章主要介绍了Java原型模式的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.思考问题现在有一只羊 tom,姓名为:
千家信息网最后更新 2026年11月04日Java原型模式的示例分析

这篇文章主要介绍了Java原型模式的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

1.思考问题

现在有一只羊 tom,姓名为: tom,年龄为:1,颜色为:白色,请编写程序创建和 tom羊属性完全相同的10只羊。

按照传统的思路来,我们可能会按照下面的方式去写。

那么这种写法的优缺点自然而然就出来了:

  • 优点是比较好理解,简单易操作。

  • 缺点是在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低。总是需要重新初始化对象,而不是动态地获得对象运行时的状态,不够灵活。

  • 改进的思路分析:Java中Object类是所有类的根类,Object类提供了一个 clone()方法,该方法可以将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力 => 原型模式。

2.什么是原型模式?

  • 原型模式(Prototype模式)是指: 用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。

  • 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。

  • 工作原理是: 通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即对象.clone()。

原型模式相关的类图如下:

3.克隆羊多莉案例代码(浅拷贝)

这里由于我是新建的普通Java项目,并不是maven项目,所以没法加lombok依赖。那么这里的构造器、setter/getter方法显得这个类的篇幅比较长。。。

package com.szh.prototype.shallowclone; public class Sheep implements Cloneable {    private String name;    private Integer age;    private String color;    private Sheep friend;     public Sheep(String name, Integer age, String color) {        this.name = name;        this.age = age;        this.color = color;    }     public Sheep(String name, Integer age, String color, Sheep friend) {        this.name = name;        this.age = age;        this.color = color;        this.friend = friend;    }     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     public Integer getAge() {        return age;    }     public void setAge(Integer age) {        this.age = age;    }     public String getColor() {        return color;    }     public void setColor(String color) {        this.color = color;    }     public Sheep getFriend() {        return friend;    }     public void setFriend(Sheep friend) {        this.friend = friend;    }     @Override    public String toString() {        return "Sheep{" +                "name='" + name + '\'' +                ", age=" + age +                ", color='" + color + '\'' +                ", friend=" + friend +                '}';    }     //克隆该实例,使用默认的clone方法来完成    @Override    protected Object clone()  {        Sheep sheep = null;        try {            sheep = (Sheep) super.clone();        } catch (CloneNotSupportedException e) {            System.out.println(e.getMessage());        }        return sheep;    }}
package com.szh.prototype.shallowclone; public class MainTest {    public static void main(String[] args) {        Sheep sheep = new Sheep("多莉",5,"黑白相间",new Sheep("喜羊羊",1,"白色"));         Sheep sheep2 = (Sheep) sheep.clone();        Sheep sheep3 = (Sheep) sheep.clone();        Sheep sheep4 = (Sheep) sheep.clone();        Sheep sheep5 = (Sheep) sheep.clone();         System.out.println(sheep + "  sheep.friend.hashCode = " + sheep.getFriend().hashCode());        System.out.println(sheep2 + "  sheep2.friend.hashCode = " + sheep2.getFriend().hashCode());        System.out.println(sheep3 + "  sheep3.friend.hashCode = " + sheep3.getFriend().hashCode());        System.out.println(sheep4 + "  sheep4.friend.hashCode = " + sheep4.getFriend().hashCode());        System.out.println(sheep5 + "  sheep5.friend.hashCode = " + sheep5.getFriend().hashCode());    }}

从上面的运行结果中可以看到,Sheep类中的前三个成员属性都可以成功的拷贝,但是最后一个friend,它表示羊的朋友(也是Sheep类型,就是引用类型了)。而当我们拷贝完成之后,应该来说都是不一样的新的对象,但是它们中的friend属性的hashCode居然是一样的!!! 这里我们就要来聊一聊深拷贝和浅拷贝了。

浅拷贝:

  • 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

  • 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址〉复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

  • 前面我们克隆羊就是浅拷贝。浅拷贝是使用默认的clone()方法来实现:sheep= (Sheep) super.clone();

深拷贝:

  • 复制对象的所有基本数据类型的成员变量值。

  • 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象(包括对象的引用类型)进行拷贝。

  • 深拷贝实现方式1: 重写clone方法来实现深拷贝。

  • 深拷贝实现方式2: 通过对象序列化实现深拷贝(推荐)。

4.深拷贝代码案例

package com.szh.prototype.deepclone; import java.io.Serializable; public class DeepCloneableTarget implements Serializable, Cloneable {     private static final long serialVersionUID = 1L;    private String cloneName;    private String cloneClass;     public DeepCloneableTarget(String cloneName, String cloneClass) {        this.cloneName = cloneName;        this.cloneClass = cloneClass;    }     @Override    public String toString() {        return "DeepCloneableTarget{" +                "cloneName='" + cloneName + '\'' +                ", cloneClass='" + cloneClass + '\'' +                '}';    }     //因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }}
package com.szh.prototype.deepclone; import java.io.*; public class DeepPrototype implements Serializable, Cloneable {     public String name; //String 属性    public DeepCloneableTarget deepCloneableTarget;// 引用类型     public DeepPrototype() {        super();    }     @Override    public String toString() {        return "DeepPrototype{" +                "name='" + name + '\'' +                ", deepCloneableTarget=" + deepCloneableTarget +                '}';    }     //深拷贝 - 方式 1 使用clone 方法    @Override    protected Object clone() throws CloneNotSupportedException {        Object deep = null;        deep = super.clone();        DeepPrototype deepPrototype = (DeepPrototype) deep;        deepPrototype.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();        return deepPrototype;    }     //深拷贝 - 方式2 通过对象的序列化实现 (推荐)    public Object deepClone() {        //创建流对象        ByteArrayOutputStream bos = null;        ObjectOutputStream oos = null;        ByteArrayInputStream bis = null;        ObjectInputStream ois = null;         try {            //序列化            bos = new ByteArrayOutputStream();            oos = new ObjectOutputStream(bos);            oos.writeObject(this);             //反序列化            bis = new ByteArrayInputStream(bos.toByteArray());            ois = new ObjectInputStream(bis);            DeepPrototype copyObj = (DeepPrototype) ois.readObject();            return copyObj;        } catch (Exception e) {            e.printStackTrace();            return null;        } finally {            //关闭流            try {                ois.close();                bis.close();                oos.close();                bos.close();            } catch (Exception e2) {                System.out.println(e2.getMessage());            }        }    }}
package com.szh.prototype.deepclone; public class MainTest {    public static void main(String[] args) throws Exception {        DeepPrototype prototype = new DeepPrototype();        prototype.name = "张起灵";        prototype.deepCloneableTarget = new DeepCloneableTarget("小哥","闷油瓶");         //方式1 完成深拷贝        DeepPrototype prototype2 = (DeepPrototype) prototype.clone();        System.out.println("方式1 完成深拷贝");        System.out.println("prototype.name = " + prototype.name + ", prototype.deepCloneableTarget = " + prototype.deepCloneableTarget);        System.out.println("prototype.deepCloneableTarget.hashCode = " + prototype.deepCloneableTarget.hashCode());        System.out.println("-------------------------------------------------------");        System.out.println("prototype2.name = " + prototype2.name + ", prototype2.deepCloneableTarget = " + prototype2.deepCloneableTarget);        System.out.println("prototype2.deepCloneableTarget.hashCode = " + prototype2.deepCloneableTarget.hashCode());        System.out.println("==============================================================================");         //方式2 完成深拷贝        DeepPrototype prototype3 = (DeepPrototype) prototype.deepClone();        System.out.println("方式2 完成深拷贝");        System.out.println("prototype.name = " + prototype.name + ", prototype.deepCloneableTarget = " + prototype.deepCloneableTarget);        System.out.println("prototype.deepCloneableTarget.hashCode = " + prototype.deepCloneableTarget.hashCode());        System.out.println("-------------------------------------------------------");        System.out.println("prototype3.name = " + prototype3.name + ", prototype3.deepCloneableTarget = " + prototype3.deepCloneableTarget);        System.out.println("prototype3.deepCloneableTarget.hashCode = " + prototype3.deepCloneableTarget.hashCode());    }}

5.原型模式总结

  • 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。

  • 不用重新初始化对象,而是动态地获得对象运行时的状态。

  • 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码。

  • 在实现深克隆的时候可能需要比较复杂的代码。

  • 缺点: 需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp原则。

感谢你能够认真阅读完这篇文章,希望小编分享的"Java原型模式的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

对象 拷贝 原型 模式 成员 类型 方式 变量 属性 方法 数据 代码 序列 篇文章 分析 复杂 也就是 实例 运行 示例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 博彦科技互联网金融 云信互联网科技有限公司 朗新科技与工业互联网 高科技与互联网 互联网金融公司科技 上游互联网科技 郑州华宇互联网科技 卓越科技互联网 招聘 互联网科技热点资讯 中国互联网有什么科技含量 汽车互联网创新科技园 河南猎农互联网科技有限公司 移动互联网科技公司 互联网科技扶贫时间 亳州好赞互联网科技有限公司 企晟互联网信息科技有限公司 卡尔迅互联网科技有限公司 35岁以上互联网科技行业 互联网科技自媒体灵感 山东亿川互联网科技有限责任公司 互联网佳科技有限公司 厦门中拓互联网络科技有限公司 河南真二互联网科技有限公司 互联网科技卖菜 卓越科技(互联网 ) 小米互联网科技园设置 来此购互联网科技有限公司 元气玛特互联网科技公司是外包吗 雨阳互联网卡科技有限公司 易企秀互联网科技是做什么的
0