java27种设计模式,java23种设计模式——四、原型模式

本文详细讲解了Java中原型模式的实现,通过实例展示了浅克隆和深克隆的区别。浅克隆仅复制对象自身,引用对象不变;深克隆则包括值类型和引用类型成员的复制。重点介绍了如何在序列化中实现深克隆以确保对象独立性。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

举个例子,就是当我们需要给电脑安装win10系统时需要去官网上下载win10系统的安装包。而安装包的大小都是很耗时的,还需要另一台电脑来操作。如果我们下载了一个安装包放在我们的u盘里,之后需要安装win10时是不是就省去了中间寻找,下载等时间呢

原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下

2|1浅克隆

新建一个实体类Sheep实现Cloneable 接口,重写clone()方法

/**

* @author codermy

* @createTime 2020/5/14

*/public class Sheep implements Cloneable{    private String name;    private int age;    private String sex;    public String getName() {        return name;

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

}    public int getAge() {        return age;

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

}    public String getSex() {        return sex;

}    public void setSex(String sex) {        this.sex = sex;

}    public Sheep(String name, int age, String sex) {        this.name = name;        this.age = age;        this.sex = sex;

}    @Override

public String toString() {        return "Sheep{" +                "name='" + name + '\'' +                ", age=" + age +                ", sex='" + sex + '\'' +                '}';

}    //克隆该实例,使用默认的clone方法

@Override

protected Object clone() throws CloneNotSupportedException {

Sheep sheep =null;

sheep = (Sheep)super.clone();        return sheep;

}

}

测试

/**

* @author codermy

* @createTime 2020/5/14

*/public class Client {    public static void main(String[] args) throws CloneNotSupportedException {

Sheep sheep = new Sheep("tom",1,"male");

Sheep sheep1 = (Sheep)sheep.clone();

System.out.println(sheep.hashCode());

System.out.println(sheep);

System.out.println(sheep1.hashCode());

System.out.println(sheep1);

sheep1.setAge(2);

System.out.println(sheep1);

System.out.println(sheep);

}

}

输出

1163157884

Sheep{name='tom', age=1, sex='male'}

1956725890

Sheep{name='tom', age=1, sex='male'}

Sheep{name='tom', age=2, sex='male'}

Sheep{name='tom', age=1, sex='male'}

在浅克隆中,被复制对象的所有普通成员变量都具有与原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象。

我们先新建一个Pearson类,作为对象属性

/**

* @author codermy

* @createTime 2020/7/24

*/public class Person implements Cloneable{

String name;    public String getName() {        return name;

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

}    public Person(){

}    public Person(String name){        this.name = name;

}

@Override

public String toString() {        return "Person{" +                "name='" + name + '\'' +                '}';

}

@Override

protected Object clone() throws CloneNotSupportedException {        return super.clone();

}

}

我们先给Sheep实体类种添加一个对象属性

/**

* @author codermy

* @createTime 2020/6/16

*/public class Sheep implements Cloneable {    private String name;    private int age;    private String sex;    public Person owner;//对象引用

public String getName() {        return name;

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

}    public int getAge() {        return age;

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

}    public String getSex() {        return sex;

}    public void setSex(String sex) {        this.sex = sex;

}    public Person getOwner() {        return owner;

}    public void setOwner(Person owner) {        this.owner = owner;

}    public Sheep(String name, int age, String sex, Person owner) {        this.name = name;        this.age = age;        this.sex = sex;        this.owner = owner;

}    @Override

public String toString() {        return "Sheep{" +                "name='" + name + '\'' +                ", age=" + age +                ", sex='" + sex + '\'' +                ", owner=" + owner +                '}';

}    //克隆该实例,使用默认的clone方法

@Override

protected Object clone() throws CloneNotSupportedException {

Sheep sheep =null;

sheep = (Sheep)super.clone();        return sheep;

}

}

测试类中测试

/**

* @author codermy

* @createTime 2020/6/16

*/public class Client {    public static void main(String[] args) throws CloneNotSupportedException {

Person owner = new Person("马云");

Sheep sheep = new Sheep("tom",1,"male", owner);//新建sheep类

Sheep sheep1 = (Sheep)sheep.clone();//克隆该类

System.out.println(sheep.hashCode() + "  " + sheep.owner.hashCode());

System.out.println(sheep + " "+ sheep.owner);

System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode());

System.out.println(sheep1 + " " + sheep1.owner);

sheep1.owner.setName("马化腾");

System.out.println(sheep.owner);

System.out.println(sheep1.owner);

}

}

输出

1163157884  1956725890Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}356573597 1956725890Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}

Person{name='马化腾'}

Person{name='马化腾'}

我们可以看出浅克隆时对象的引用仅仅是指向了原空间,而并没有复制对象。

2|2深克隆

在深克隆中,对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。

自定义clone过程实现深克隆

将上面Sheep类中的clone方法改写

@Override

protected Object clone() throws CloneNotSupportedException {

Sheep sheep =null;

sheep = (Sheep)super.clone();

sheep.owner = (Person) sheep.owner.clone();//引用对象的克隆方法

return sheep;

}

测试类测试

public class Client {    public static void main(String[] args) throws CloneNotSupportedException {

Person owner = new Person("马云");

Sheep sheep = new Sheep("tom",1,"male", owner);

Sheep sheep1 = (Sheep)sheep.clone();

System.out.println(sheep.hashCode() + "  " + sheep.owner.hashCode());

System.out.println(sheep + " "+ sheep.owner);

System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode());

System.out.println(sheep1 + " " + sheep1.owner);

sheep1.owner.setName("马化腾");

System.out.println(sheep.owner);

System.out.println(sheep1.owner);

}

}

输出

1163157884  1956725890

Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}

356573597 1735600054

Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}

Person{name='马云'}

Person{name='马化腾'}

这时候我们已经实现了深克隆,但是总觉得有点“浅浅克隆”的意思,如果person类中还有对象引用那不就是。。

禁止套娃

3d76597d573f6a5c9e9cf3908806218a.png

序列化实现深克隆

两个实体类实现序列化接口

Person类

public class Person implements Serializable {

String name;    public String getName() {        return name;

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

}    @Override

public String toString() {        return "Person{" +                "name='" + name + '\'' +                '}';

}    public Person(String name){        this.name = name;

}

}

Sheep类

/**

* @author codermy

* @createTime 2020/6/16

*/public class Sheep implements  Serializable {    private String name;    private int age;    private String sex;    public Person owner;//对象引用

public String getName() {        return name;

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

}    public int getAge() {        return age;

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

}    public String getSex() {        return sex;

}    public void setSex(String sex) {        this.sex = sex;

}    public Person getOwner() {        return owner;

}    public void setOwner(Person owner) {        this.owner = owner;

}    public Sheep() {

}    public Sheep(String name, int age, String sex, Person owner) {        this.name = name;        this.age = age;        this.sex = sex;        this.owner = owner;

}    @Override

public String toString() {        return "Sheep{" +                "name='" + name + '\'' +                ", age=" + age +                ", sex='" + sex + '\'' +                ", owner=" + owner +                '}';

}

}

实现

**

* @author codermy

* @createTime 2020/7/24

*/public class Client {    public static void main(String[] args) throws Exception {

Person owner = new Person("马云");

Sheep sheep = new Sheep("tom",1,"male", owner);

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(sheep);

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));

Sheep sheep1 =(Sheep) ois.readObject();

bos.flush();oos.flush();

bos.close();oos.close();

ois.close();

System.out.println("Sheep: " + sheep);

System.out.println("Sheep1: " + sheep1);

System.out.println("================================");

System.out.println("Sheep: " + sheep.hashCode() + "++++++++++" + sheep.owner.hashCode());

System.out.println("Sheep1: " + sheep1.hashCode() + "++++++++++" + sheep1.owner.hashCode());

System.out.println("================================");

sheep1.owner.setName("马化腾");

System.out.println("Sheep: " + sheep.owner);

System.out.println("Sheep1: " + sheep1.owner);

}

}

输出

1163157884  1956725890

Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}

356573597 1735600054

Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}

Person{name='马云'}

Person{name='马化腾'}

2|3原型模式的优缺点

优点:原型模式是在内存中二进制流的拷贝,要比new一个对象的性能要好,特别是需要产生大量对象时。

缺点:直接在内存中拷贝,构造函数是不会执行的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值