Spring设计模式——原型模式
原型模式
原型模式(Prototype Pattern),是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
原型模式主要适用于以下场景:
- 类初始化消耗资源较多
- 使用new生成一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数比较复杂
- 在循环中产生大量对象
浅拷贝
先创建原型Prototype接口:
/** * @author ss_419 */ public interface Prototype { Prototype clone(); }
创建具体需要克隆的类ConcretePrototypeA:
package org.example.spring.designpattern.prototype.shallow; import java.util.List; /** * TODO * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:15 */ public class ConcretePrototypeA implements Prototype { private int age; private String name; private List hobbies; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getHobbies() { return hobbies; } public void setHobbies(List hobbies) { this.hobbies = hobbies; } @Override public Prototype clone() { ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA(); concretePrototypeA.setAge(this.getAge()); concretePrototypeA.setName(this.getName()); concretePrototypeA.setHobbies(this.getHobbies()); return concretePrototypeA; } @Override public String toString() { return "ConcretePrototypeA{" + "age=" + age + ", name='" + name + '\'' + ", hobbies=" + hobbies + '}'; } }
创建Client类:
package org.example.spring.designpattern.prototype.shallow; /** * TODO * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:17 */ public class Client { private Prototype prototype; public Client(Prototype prototype) { this.prototype = prototype; } public Prototype startClone(Prototype concretePrototype){ return (Prototype) concretePrototype.clone(); } }
测试代码如下:
package org.example.spring.designpattern.prototype.shallow; import java.util.ArrayList; import java.util.List; /** * TODO * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:20 */ public class PrototypeTest { public static void main(String[] args) { ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA(); concretePrototypeA.setAge(18); concretePrototypeA.setName("ss"); List hobbies = new ArrayList<String>(); hobbies.add("唱"); hobbies.add("跳"); hobbies.add("Rap"); concretePrototypeA.setHobbies(hobbies); System.out.println(concretePrototypeA); // 创建client对象,准备开始克隆 Client client = new Client(concretePrototypeA); ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototypeA); System.out.println(concretePrototypeClone); System.out.println("concretePrototypeA.getHobbies() = " + concretePrototypeA.getHobbies()); System.out.println("concretePrototypeClone.getHobbies() = " + concretePrototypeClone.getHobbies()); System.out.println("对象地址比较:" +(concretePrototypeClone.getHobbies() == concretePrototypeA.getHobbies())); } }
浅拷贝只是完整复制了值类型数据,没有赋值引用对象,换言之,所有的引用对象仍然指向原来的对象,显然这不是我们想要的结果。
深拷贝
创建原型猴子类Monkey:
package org.example.spring.designpattern.prototype.deep; import java.util.Date; /** * TODO 深拷贝对象——猴子🐒 * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:41 */ public class Monkey { public int height; public int weight; public Date birthDate; }
创建引用对象JinGuBang:
package org.example.spring.designpattern.prototype.deep; import java.io.Serializable; /** * TODO 引用对象JinGuBang * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:43 */ public class JinGuBang implements Serializable { public float h = 100; public float d = 10; public void big(){ this.d *= 2; this.h *= 2; } public void small(){ this.d /= 2; this.h /= 2; } }
创建具体的对象齐天大圣类QiTianDaSheng:
package org.example.spring.designpattern.prototype.deep; import java.io.*; import java.util.Date; /** * TODO 具体对象齐天大圣,归根结底还是个猴儿~ * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:45 */ public class QiTianDaSheng extends Monkey implements Cloneable, Serializable { public JinGuBang jinGubang; public QiTianDaSheng() { // 只是初始化 this.birthDate = new Date(); this.jinGubang = new JinGuBang(); } @Override protected Object clone() throws CloneNotSupportedException { // 调用指定的拷贝方法(深deep、浅shallow) return this.deepClone(); } // 深拷贝 public Object deepClone() { try{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); // 写入当前对象 oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); QiTianDaSheng copy = (QiTianDaSheng)ois.readObject(); copy.birthDate = new Date(); return copy; }catch (Exception e){ e.printStackTrace(); return null; } } public QiTianDaSheng shallowClone(QiTianDaSheng target){ QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); qiTianDaSheng.height = target.height; qiTianDaSheng.weight = target.weight; qiTianDaSheng.jinGubang = target.jinGubang; qiTianDaSheng.birthDate = new Date(); return qiTianDaSheng; } }
测试代码如下:
package org.example.spring.designpattern.prototype.deep; /** * TODO 深拷贝测试代码 * * @author ss_419 * @version 1.0 * @date 2023/3/9 09:53 */ public class DeepCloneTest { public static void main(String[] args) { QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); try { QiTianDaSheng clone = (QiTianDaSheng) qiTianDaSheng.clone(); System.out.println("深拷贝:" + (qiTianDaSheng.jinGubang == clone.jinGubang)); }catch (Exception e){ e.printStackTrace(); } QiTianDaSheng q = new QiTianDaSheng(); QiTianDaSheng n = q.shallowClone(q); System.out.println("浅拷贝:" + (q.jinGubang == n.jinGubang)); } }
运行结果如下:
我们可以发现,深拷贝的引用类对象是不同的指向,而浅拷贝的引用地址是相同的,这意味着深拷贝复制的是值,而不是引用地址了。
posted on 2023-03-09 10:04 JavaCoderPan 阅读(314) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南