06-设计模式——原型模式
设计模式——原型模式
知识点:
- Cloneable接口/Pbject#clone方法 详解
- 浅拷贝/深拷贝
- 序列化机制实现深拷贝
模式定义:
指原型实例指定创建对象的种类,并且通过拷贝(复制)这些原型创建新的对象
应用场景:
当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式
优点:
- 可以不耦合具体类的情况下克隆对象
- 避免重复的初始化代码
- 更方便的构建复杂对象
package com.example.designpatterns.prototype;import cn.hutool.Hutool;import cn.hutool.core.util.HashUtil;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.*;/** * @program: DesignPatterns * @description: 原型模式 * @author: Coder_Pan * @create: 2022-04-13 11:12 **/public class PrototypeTest { public static void main(String[] args) throws CloneNotSupportedException { BaseInfo baseInfo = new BaseInfo("ssss"); Product product = new Product("part1", "part2", 3, 4, 5,baseInfo); Product clone = product.clone(); System.out.println("克隆出来的对象与源对象不相等"); System.out.println(product == clone); System.out.println(product); System.out.println(clone); product.getBaseInfo().setCompanyName("pppp"); System.out.println(product); System.out.println("依旧存在关联,这样是不对的,需要通过两次拷贝,对引用对象也进行拷贝才正确"); System.out.println(clone); }}@Dataclass BaseInfo implements Cloneable,Serializable{ /** * 实现序列化,如果需要进行持久化操作,必须加版本号 */ private static final long serialVersionUID = 42L; private String companyName; public BaseInfo(String ssss) { this.companyName = ssss; } @Override protected BaseInfo clone() throws CloneNotSupportedException { return ((BaseInfo) super.clone()); } @Override public String toString() { return super.hashCode() + "BaseInfo{" + "companyName='" + companyName + '\'' + '}'; }}/** * 定义产品实例 */@Data@AllArgsConstructor@NoArgsConstructorclass Product implements Cloneable,Serializable{ /** * 实现序列化,如果需要进行持久化操作,必须加版本号 */ private static final long serialVersionUID = 42L; private String part1; private String part2; private Integer part3; private Integer part4; private Integer part5; private BaseInfo baseInfo; /** * V1 - 使用Java中的clone方式实现原型模式 * @return * @throws CloneNotSupportedException */ @Override protected Product clone() throws CloneNotSupportedException { //本对象拷贝 Product clone = (Product) super.clone(); //本对象中使用到的对象的拷贝 == > 深拷贝 BaseInfo clone1 = this.baseInfo.clone(); clone.setBaseInfo(clone1); return clone; } /** * V2 - 通过Java序列化的方式进行拷贝,实现原型模式 * 若想使用序列化操作,则在涉及到拷贝的每个class上都应实现Serializable * 这个方式由CPU来执行,比较消耗性能,速度比较慢 * * 不推荐使用..... * @return * @throws CloneNotSupportedException */ protected Product clone1() throws CloneNotSupportedException { //1、定义输出流 ByteArrayOutputStream baos = new ByteArrayOutputStream( ); try { ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject( this ); } catch (IOException e) { e.printStackTrace(); } //拿到输入流对象 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(baos.toByteArray()); //从内存中恢复数据 try { ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream); Product product = (Product) ois.readObject(); return product; //这里完成深拷贝 } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } @Override public String toString() { return super.hashCode() + "Product{" + "part1='" + part1 + '\'' + ", part2='" + part2 + '\'' + ", part3=" + part3 + ", part4=" + part4 + ", part5=" + part5 + ", baseInfo=" + baseInfo + '}'; }}