原型模式

本文详细阐述了原型模式在创建对象中的应用,介绍了如何通过实现Cloneable接口和重写clone方法实现对象克隆,并区分了浅拷贝与深拷贝的概念。通过实例演示了浅拷贝问题及其解决方案,以及如何在Location类中实现深拷贝以保持独立性。
摘要由CSDN通过智能技术生成

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

在这里插入图片描述
如何实现:

1,实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。

2,重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。

深拷贝和浅拷贝的区别

假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

浅拷贝

场景1:Person实现了Cloneable接口并重写了clone方法,Person有三个属性,age,score和一个Location对象引用属性,首先new出一个p1对象,p2对象来自于p1对象的clone。

实现代码:

/**
 * @Author huyouting
 * @Date 2021/2/29 10:39
 * @Description:
 */
public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person();
        Person p2 = (Person)p1.clone();
        System.out.println(p2.age+" "+p2.score);
        System.out.println(p2.loc);

        System.out.println(p1.loc ==p2.loc);
        p1.loc.street ="sh";
        System.out.println(p2.loc);
    }
}

class  Person implements Cloneable{
    int age = 8;
    int score =100;

    Location loc = new Location("bj",22);
    @Override
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}

class Location{
    String street;
    int roomNo;

    @Override
    public String toString() {
        return "Location{" +
                "street='" + street + '\'' +
                ", roomNo=" + roomNo +
                '}';
    }

    public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
    }
}

运行结果:
在这里插入图片描述
结果发现当改变p1对象的Location属性时,p2对象的Location也发生了改变,因为p1,p2对象的Location引用到了同一个内存地址,当内存中的属性改变时,由于p2同样引用这个属性,所有p2的Location也发生了改变,这就是浅拷贝。

思考:如果不想改变,该如何解决?

深拷贝

解决方法就是Location同样实现Cloneable接口并重写了clone方法,当Person对象进行clone时,Location同样进行clone,具体代码实现如下:

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person();
        Person p2 = (Person) p1.clone();
        System.out.println(p2.age + " " + p2.score);
        System.out.println(p2.loc);

        System.out.println(p1.loc == p2.loc);
        p1.loc.street = "sh";
        System.out.println(p2.loc);
    }
}

class Person implements Cloneable {
    int age = 8;
    int score = 100;

    Location loc = new Location("bj", 22);

    @Override
    public Object clone() throws CloneNotSupportedException {
        Person p = (Person) super.clone();
        p.loc = (Location) loc.clone();
        return p;
    }
}

class Location implements Cloneable {
    String street;
    int roomNo;

    @Override
    public String toString() {
        return "Location{" +
                "street='" + street + '\'' +
                ", roomNo=" + roomNo +
                '}';
    }

    public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

此时的运行结果:
在这里插入图片描述
当p1的Location属性发生改变时,p1的Location并没有发生改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值