【创建型设计模式】原型模式prototype

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【创建型设计模式】原型模式prototype,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

原型模式

看完建造者模式之后,我来到了创建型模式的最后一个部分—-原型模式

理解

定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

使用场景:当我们通过new产生一个对象需要非常繁琐的数据准备或者访问权限,则可以使用原型模式,这样可以提高效率

注意:
1、区分什么是深复制、什么是浅复制
2、原型模式中的原型对象需要实现Cloneable接口
3、用序列化和反序列化实现深克隆时,原型对象还需要需要实现Serializable接口

代码样例

1、浅复制
我们创建一个继承Cloneable接口的Sheep类,并且重写clone()方法

import java.io.Serializable;
import java.util.Date;

public class Sheep implements Cloneable, Serializable {
    private String name;

    private Date birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 浅复制仅仅是对原型对象进行克隆,并不克隆原型对象的属性所指向的那个对象
        Object object = super.clone();
        return object;
    }

    public Sheep() {
    }

    public Sheep(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

然后写个测试类,使用clone()方法克隆出两个新的对象sheep2和sheep3

import java.util.Date;

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date = new Date(1234231231L);
        Sheep sheep1 = new Sheep("多莉", date);
        System.out.println(sheep1.getName());
        System.out.println(sheep1.getBirthday());

        Sheep sheep2 = (Sheep) sheep1.clone();
        System.out.println(sheep2.getName());
        System.out.println(sheep2.getBirthday());

        Sheep sheep3 = (Sheep) sheep1.clone();
        // 浅复制时,修改原型对象的属性值,会影响之前的克隆对象
        date.setTime(12314112312L);
        System.out.println(sheep3.getName());
        System.out.println(sheep3.getBirthday());
    }
}

运行测试类之后,可以看出修改原型对象sheep1的属性值后,会影响到克隆对象sheep3的属性
因为浅复制时,克隆对象的属性所指向也是原型对象的属性
在这里插入图片描述

2、深复制
我们创建一个继承Cloneable接口的Sheep2类,并且重写clone()方法,与浅复制不同的是,我们对原型对象的属性也进行了克隆

import java.util.Date;

public class Sheep2 implements Cloneable {
    private String name;

    private Date birthday;

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

        // 要实现深复制,就需要在重写clone方法时对原型对象的属性也进行克隆,相当于创建了一个新的对象去赋值给克隆对象的属性
        Sheep2 sheep2 = (Sheep2) obj;
        sheep2.birthday = (Date) this.birthday.clone();
        return sheep2;
    }

    public Sheep2() {
    }

    public Sheep2(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

同样的我们编写一个测试类进行测试

import java.util.Date;

public class Client2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date = new Date(12314123113L);
        Sheep2 sheep = new Sheep2();
        sheep.setName("多莉2");
        sheep.setBirthday(date);
        System.out.println(sheep.getName());
        System.out.println(sheep.getBirthday());

        Sheep2 sheep2 = (Sheep2) sheep.clone();
        // 深复制时,修改原对象的属性,不会对已经克隆好的对象产生影响
        date.setTime(12314112312L);
        System.out.println(sheep2.getName());
        System.out.println(sheep2.getBirthday());
    }
}

运行测试类之后,可以看出修改原型对象的属性值后,不会影响到克隆对象的属性
因为深复制时,克隆对象的属性所指向不再是原型对象的属性,我们相当于创建了一个新的属性对象赋予给克隆对象的那个属性,所以即使原型对象的属性值变了也不会对克隆对象产生影响
在这里插入图片描述
3、使用序列化与反序列化实现深复制
我们在创建Sheep类时,还需要继承一个Serializable接口
然后我们编写测试类进行测试

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

public class Client3 {
    public static void main(String[] args) throws Exception {
        Date date = new Date(1234231231L);
        Sheep sheep1 = new Sheep("多莉", date);
        System.out.println(sheep1.getBirthday());

        // 注意,使用序列化与反序列化深克隆原型对象时,原型对象的类需要实现Serializable接口
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(sheep1);
        byte[] bytes = bos.toByteArray();

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream inputStream = new ObjectInputStream(bis);

        Sheep sheep2 = (Sheep) inputStream.readObject();
        date.setTime(12314112312L);
        System.out.println(sheep2.getBirthday());
    }
}

我们发现,即使修改了原型对象的属性值,也不会对克隆的对象产生影响
在这里插入图片描述
如有错误,欢迎指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/136822.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!