Java源码阅读基础----设计模式----原型模式

    原型模式(prototype):就是说的java中的克隆技术,指定一个原型来克隆,克隆后的对象拥有原型中所有的属性。说到克隆大家肯定会想到Object类中的clone方法或者 cloneable接口。
    大家可以看看我写的关于Object类的文章: https://blog.csdn.net/lyz812672598/article/details/80017802
    说到拷贝,又要不说另一个概念:浅拷贝和深拷贝。

    浅拷贝:通俗点说就是对原型对象引用的拷贝(打个比喻,就像一个人站在一面镜子面前,你看着镜子里的人和站在镜子面前的人好像确实变成了两个人,长个也一摸一样,但是“原型人”动一下,镜子中的人也会动一下,有依赖关系)。
     深拷贝:对原型对象中所有成员的值进行拷贝,直到最底层(打个比喻,就像双胞胎一样,你看着两个人一模一样,但是他们之间不存在依赖关系,一个人闭眼睛了,另一个人照样睁着眼睛)。

    话不多说,直接上代码,用代码说话。

public class Student {
    public String name;

    public Integer age;

    public String sex;
}
 
public class ProtoType implements Cloneable {

    public Integer high;

    public Student student;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        ProtoType obj = (ProtoType)super.clone();
        return obj;

    }
}
 
 
public class ProtoTypeTest {

    public static void main(String[] args) {
        Student student = new Student();
        student.name = "马云云";
        student.age = 18;
        student.sex = "男";
        ProtoType protoType = new ProtoType();
        protoType.high = 180;
        protoType.student = student;
        ProtoType protoType1 = null;
        try {
            protoType1 = (ProtoType) protoType.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        student.name = "雷小军";
        student.age = 21;
        student.sex = "女";
        System.out.println("原型对象地址:");
        System.out.println(protoType);
        System.out.println(protoType1);
        System.out.println("原型对象成员地址:");
        System.out.println(protoType.student);
        System.out.println(protoType1.student);
        System.out.println(protoType.student.name);
        System.out.println(protoType1.student.name);
        System.out.println(protoType.student.age);
        System.out.println(protoType1.student.age);
        System.out.println(protoType.student.sex);
        System.out.println(protoType1.student.sex);
    }
}
原型对象地址: com.design.pattern.proto.ProtoType@140e19d com.design.pattern.proto.ProtoType@17327b6 原型对象成员地址: com.design.pattern.proto.vo.Student@14ae5a5 com.design.pattern.proto.vo.Student@14ae5a5 雷小军 雷小军 21 21 女 女
Process finished with exit code 0

    通过代码输出发现,我们用了clone方法(未重写,用的是父类方法)后,虽然按照原型给我们确实复制了一个出来,但是克隆出来的对象里面的对象压根还是原型里面的对象,有兴趣的同学可以把”student“中的属性改一改,看看是否最后输出结果是否一样。所以我们发现浅拷贝不能完全摆脱原型的控制,原型中的成员就是拷贝后的对象成员
    那么我们怎么做到深克隆呢?刚刚也说了只要把对象的成员也拷贝一份即可,直到最底层。
 
public class Student implements Cloneable {
    public String name;

    public Integer age;

    public String sex;

    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
}
public class ProtoType implements Cloneable {

    public Integer high;

    public Student student;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        ProtoType obj = (ProtoType)super.clone();
        obj.student = student.clone();
        return obj;

    }
}
原型对象地址: com.design.pattern.proto.ProtoType@140e19d com.design.pattern.proto.ProtoType@17327b6 原型对象成员地址: com.design.pattern.proto.Student@14ae5a5 com.design.pattern.proto.Student@131245a 雷小军 马云云 21 18 女 男
Process finished with exit code 0
    通过输出我们看到了,原型对象成员的改变,对克隆对象的影响消失了,即没有依赖关系了。但是上面的方法也有一个很大的缺陷,就是如果我们对象里的结构非常复杂的话,那么我们重写clone方法的代价就特别大,所以不推荐大家这么去做。那更简单的方法是什么呢?就是我们java里的序列化,可以帮我们达到深克隆的目的。看代码:
public class Student implements Serializable {
    public String name;

    public Integer age;

    public String sex;
}
public class ProtoType implements Cloneable,Serializable {

    public Integer high;

    public Student student;

    @Override
    protected Object clone() throws CloneNotSupportedException{
        Object obj = null;
        try {
            obj = deepClone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  obj;
    }

    private Object deepClone() throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        ProtoType obj = (ProtoType) ois.readObject();
        return obj;
    }
}
 
原型对象地址: com.design.pattern.proto.ProtoType@10bedb4 com.design.pattern.proto.ProtoType@1eba861 原型对象成员地址: com.design.pattern.proto.Student@10455d6 com.design.pattern.proto.Student@1480cf9 雷小军 马云云 21 18 女 男
Process finished with exit code 0
    从输出可以看出,同样可以达到深克隆的目的。其实原型模式主要是为了让我们避免多次创建对象(因为每创建一次对象就需要初始化一次,同样Objec文章里讲到),避免了其构造过程中引起系统的消耗。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值