设计模式Java实现-原型模式

楔子

原型模式是一种创建型设计模式,它允许复制现有对象来创建新对象,而不是通过实例化新对象,这样可以在创建复杂对象时,节约时间。如果你经常使用 JavaScript,那么原型模式是一种比较常用的开发模式,原型链也是面试经常被问到的问题。但是如果你是使用Java的后端程序员,那么原型模式的确是很少在业务中运用的。

需求背景

我们从远程RPC获取了一份数据,假设为数据A,在不影响数A的情况下,我们需要从数据A复制一份数据B,然后在数据B上进行操作。

分析设计

因为是将数据A复制到数据B,所以可以实现Cloneable,使用原型模式。

又因为不能影响数据A,所以我们需要考虑使用浅拷贝还是深拷贝。

怎么理解浅拷贝和深拷贝呢?

浅拷贝是按位拷贝对象,会创建一个新对象,但不会修改原对象的值。它复制的是对象的引用地址,没有开辟新的栈,所以复制的结果是两个对象指向同一个地址。因此,当修改其中一个对象的属性时,另一个对象的属性也会跟着改变。

深拷贝是复制对象本身,不共享内存。这意味着它会创建一个新的对象,并且复制原对象的所有字段以及字段所指向的动态分配内存。因此,修改新对象不会影响原对象。

深拷贝相比于浅拷贝速度较慢并且花销较大,因为它需要复制更多的数据。

举个例子,浅拷贝就好比钢铁侠的机甲,不管他制造了多少套,但是他们的AI都是贾维斯,都是一个。 而深拷贝,就是一套机甲一个AI。

所以我们上面的需求,需要使用深拷贝。

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

原型模式URL.jpg

模块名称

prototype

模块地址

gitee.com/diqirenge/d…

模块描述

原型模式代码示例

浅拷贝

代码实现

1、首先我们实现浅拷贝

 

java

复制代码

/** * 原型模式 * 关注公众号【奔跑的码畜】,一起进步不迷路 * * @author 第七人格 * @date 2023/11/21 */ public class RpcData implements Cloneable { private String name; private String age; private Pet pet; public static class Pet { private String name; private String age; private String tyep; public Pet() { } public Pet(String name, String age, String tyep) { this.name = name; this.age = age; this.tyep = tyep; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getTyep() { return tyep; } public void setTyep(String tyep) { this.tyep = tyep; } @Override public String toString() { System.out.println("Pet{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", tyep='" + tyep + '\'' + '}'); return super.toString(); } } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } @Override public String toString() { System.out.println("RpcData{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", pet=" + pet + '}'); return super.toString(); } }

2、编写测试方法

 

java

复制代码

/** * 原型模式 * 关注公众号【奔跑的码畜】,一起进步不迷路 * * @author 第七人格 * @date 2023/11/21 */ public class RpcDataPrototypeTest { @Test public void test_shallow_copy() throws CloneNotSupportedException { System.out.println("==========浅拷贝开始=========="); RpcData rpcData = new RpcData(); Pet pet = new Pet("小黑", "1", "dog"); rpcData.setName("第七人格"); rpcData.setAge("18"); rpcData.setPet(pet); RpcData cloneData = (RpcData) rpcData.clone(); Pet clonePet = cloneData.getPet(); System.out.println("原型对象和克隆对象是否是同一个对象:" + (rpcData == cloneData)); System.out.println("原型对象和克隆对象中的宠物是否是同一个对象:" + (pet == clonePet)); System.out.println("==========浅拷贝结束=========="); } }

3、测试结果

①执行test_shallow_copy方法

==========浅拷贝开始==========

原型对象和克隆对象是否是同一个对象:false

原型对象和克隆对象中的宠物是否是同一个对象:true

==========浅拷贝结束==========

实现要点

  1. 实现 Cloneable 接口,重写clone方法

深拷贝

一般有两种实现方式:

①先将对象序列化,然后再反序列化成新的对象

②递归拷贝对象、对象的引用对象以及引用对象的引用对象,直到对象属性中只有基本数据类型数据为止

我们这里只演示第一种方式

代码实现

1、RpcData和Pet实现Serializable接口

2、添加深拷贝-序列化方法

 

java

复制代码

public Object deepCopy(Object object) throws IOException, ClassNotFoundException { ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(object); ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return oi.readObject(); }

3、编写测试方法

 

java

复制代码

@Test public void test_deepCopy_copy() throws IOException, ClassNotFoundException { System.out.println("==========深拷贝开始=========="); RpcData rpcData = new RpcData(); Pet pet = new Pet("小黑", "1", "dog"); rpcData.setName("第七人格"); rpcData.setAge("18"); rpcData.setPet(pet); RpcData cloneData = (RpcData) rpcData.deepCopy(rpcData); Pet clonePet = cloneData.getPet(); System.out.println("原型对象和克隆对象是否是同一个对象:" + (rpcData == cloneData)); System.out.println("原型对象和克隆对象中的宠物是否是同一个对象:" + (pet == clonePet)); System.out.println("===========深拷贝结束=========="); }

4、测试结果

==========深拷贝开始==========

原型对象和克隆对象是否是同一个对象:false

原型对象和克隆对象中的宠物是否是同一个对象:false

===========深拷贝结束==========

实现要点

①先将对象序列化,然后再反序列化成新的对象

总结

原型模式的原理和实现都是比较简单的,主要是需要理解浅拷贝和深拷贝的原理。有机会还是要用在项目中,多实践才能掌握得更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值