【设计模式】创建型:原型模式(二)简单克隆

本文详细介绍了Java中的浅克隆和深克隆概念,通过示例代码展示了如何实现原型模式。浅克隆仅复制基本类型和引用对象的地址,而深克隆则递归复制所有引用对象。示例中展示了浅克隆导致的引用对象地址相同,进而影响到对象状态的问题。文章最后提到,为达到期望的完全独立的副本,需要采用深克隆技术。

所谓简单克隆也就是浅拷贝,即它只会拷贝对象中的基本数据类型的数据(比如,int、long),以及引用对象(比如 List)的内存地址,不会递归地拷贝引用对象本身。

PS:在 Java 语言中,Object 类的 clone() 方法执行的就是浅拷贝。

下面,我们还是通过示例来演示一下,如何实现基于浅拷贝的原型模式…

具体示例

一个标准的原型模式代码,应该是这样设计的。先创建原型 Prototype 接口:

public interface Prototype{
	Prototype clone();
}

创建具体需要克隆的对象 ConcretePrototypA:

public class ConcretePrototypeA implements Prototype {

    private int age;
    private String name;
    private List hobbies;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getHobbies() {
        return hobbies;
    }

    public void setHobbies(List hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    // 拷贝的逻辑
    public ConcretePrototypeA clone() {
    	// 创建一个新对象
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        // 直接将当前对象的值填充,不做任何多余处理
        concretePrototype.setAge(this.age);
        concretePrototype.setName(this.name);
        concretePrototype.setHobbies(this.hobbies);
        return concretePrototype;
    }

}

创建 Client 对象:

public class Client {

    private Prototype prototype;

    public Client(Prototype prototype){
        this.prototype = prototype;
    }
    public Prototype startClone(Prototype concretePrototype){
        return (Prototype)concretePrototype.clone();
    }

}

测试代码:

public class PrototypeTest {

    public static void main(String[] args) {

        // 创建一个具体的需要克隆的对象
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        // 填充属性,方便测试
        concretePrototype.setAge(18);
        concretePrototype.setName("prototype");
        List hobbies = new ArrayList<String>();
        concretePrototype.setHobbies(hobbies);
        // 打印原对象地址
        System.out.println(concretePrototype);

        // 创建Client对象,准备开始克隆
        Client client = new Client(concretePrototype);
        ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype);
        // 打印新对象地址
        System.out.println(concretePrototypeClone);
		
		// 比较两个对象的引用类型成员变量
        System.out.println("克隆对象中的引用类型地址值:" + concretePrototypeClone.getHobbies());
        System.out.println("原对象中的引用类型地址值:" + concretePrototype.getHobbies());
        System.out.println("对象地址比较:"+(concretePrototypeClone.getHobbies() == concretePrototype.getHobbies()));
    }
}

运行结果如下:

在这里插入图片描述

从中可以看到,拷贝得到的对象是一个新对象,与原对象不同;另外,这个新对象的引用类型成员变量 hobbies,与原对象的 hobbies 的地址相同;这意味着复制的不是值,而是引用的地址。这样的话,如果我们修改任一对象该属性的值 , concretePrototype 和 concretePrototypeCone 的 hobbies 值都会改变。

小结

这就是我们常说的浅克隆。只是完整复制了值类型数据,没有赋值引用对象。换言之,所有的引用对象仍然指向原来的对象,显然不是我们想要的结果。

下面我们来看深度克隆继续改造…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A minor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值