atwood-pan

 

06-设计模式——原型模式

设计模式——原型模式

知识点:

  1. Cloneable接口/Pbject#clone方法 详解
  2. 浅拷贝/深拷贝
  3. 序列化机制实现深拷贝

模式定义:

指原型实例指定创建对象的种类,并且通过拷贝(复制)这些原型创建新的对象

LuvR8s.png

应用场景:

当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式

优点:

  1. 可以不耦合具体类的情况下克隆对象
  2. 避免重复的初始化代码
  3. 更方便的构建复杂对象

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);
    }
}


@Data
class 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
@NoArgsConstructor
class 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 +
                '}';
    }
}

posted on 2022-04-13 13:21  JavaCoderPan  阅读(10)  评论(0编辑  收藏  举报  来源

导航