设计模式学习之原型模式

原型模式属于创建型模式,原型模式最典型的例子就是Java的深拷贝和浅拷贝 (clone方法)。

clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。一般而言,clone()方法满足以下的描述:

(1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。
(2)对任何的对象x,都有:x.clone().getClass() == x.getClass(),换言之,克隆对象与原对象的类型一样。
(3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。

在JAVA语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。JAVA语言的设计师在设计自己的clone()方法时,也应当遵守着三个条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的。

浅拷贝clone()

当进浅拷贝时,clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
同时,复制出来的对象具有与原对象一致的状态。虽然复制出来的对象重新在堆上开辟了内存空间,但是,
对象中各属性确保持相等。对于基本数据类型很好理解,但对于引用数据类型来说,则意味着此引用类型的属性
所指向的对象本身是相同的,并没有重新开辟内存空间存储。换句话说,引用类型的属性所指向的对象并没有复制

coding:(实现cloneable)重写clone()函数,复制一部电影:


/**
 * 导演
 * @Author: pk.zhang
 * @Date: 2020/2/11 16:57
 */
@Data
public class Director {
    private String name;
    private int age;
}

/**
 * 电影
 * @Author: pk.zhang
 * @Date: 2020/2/11 16:51
 */
@Data
public class Movie implements Cloneable {

    private String movieName;
    private int personNum;
    private Director director;

    @Override
    protected Movie clone() throws CloneNotSupportedException {
        return (Movie)super.clone();
    }
}	

Test:

class Test{

    public static void main(String[] args) throws CloneNotSupportedException {
        Movie movie1 = new Movie();
        Director director = new Director();
        director.setName("Tom.jackson");
        director.setAge(45);
        movie1.setMovieName("谍影重重");
        movie1.setPersonNum(10);
        movie1.setDirector(director);
        Movie movie2 = movie1.clone();

        System.out.println(movie1 == movie2); // false
        System.out.println(movie1.getPersonNum() == movie2.getPersonNum());// true
        System.out.println(movie1.getMovieName() == movie2.getMovieName());// true
        System.out.println(movie1.getDirector() == movie2.getDirector());// true
    }

}
深拷贝deepClone()

Java中的深复制一般是通过对象的序列化和反序列化得以实现。序列化时,需要实现Serializable接口
深拷贝的特点就是不仅在堆内存上开辟了空间以存储复制出的对象,甚至连对象中的引用类型的属性所指向
的对象也得以复制,重新开辟了堆空间存储。

coding:

需要自己手写deepClone()函数,实现如下:

/**
 * 导演
 * @Author: pk.zhang
 * @Date: 2020/2/11 16:57
 */
@Data
public class Director implements Serializable {
    private String name;
    private int age;
}

/**
 * 电影
 * @Author: pk.zhang
 * @Date: 2020/2/11 16:51
 */
@Data
public class Movie implements Serializable {

    private String movieName;
    private int personNum;
    private Director director;

    public Movie deepClone() throws IOException, ClassNotFoundException {
        // 写入当前对象的二进制流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 读出二进制流产生的新对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Movie) ois.readObject();
    }
}

TestDeepClone:

class TestDeepClone{

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Movie movie1 = new Movie();
        Director director = new Director();
        director.setName("Tom.jackson");
        director.setAge(45);
        movie1.setMovieName("谍影重重");
        movie1.setPersonNum(10);
        movie1.setDirector(director);
        Movie movie2 = movie1.deepClone();

        System.out.println(movie1 == movie2); // false
        System.out.println(movie1.getPersonNum() == movie2.getPersonNum());// true
        System.out.println(movie1.getMovieName() == movie2.getMovieName());// false
        System.out.println(movie1.getDirector() == movie2.getDirector());// false
    }

}

参考连接https://zhuanlan.zhihu.com/p/99381761

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值