设计模式之原型模式

发布时间 2023-11-25 20:27:38作者: 译林

原型模式指的是,从对象copy一个对象到另一个对象

  • 浅拷贝: 类对象copy的时候使用的是地址,基础类型会进行数据拷贝
  • 深拷贝:基础数据类型以及类对象都会进行数据copy
  • spring创建对象的时候,可以选择单例,也可以选择原型模式

原始的copy方式:

需要拷贝的类

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PrimitivePojo {

private String id;

private String name;

}

运行拷贝的类

public class Primitive {

public static void main(String[] args) {

PrimitivePojo primitivePojo = new PrimitivePojo("11", "张三");

PrimitivePojo prototypeType1 = new PrimitivePojo(primitivePojo.getId(), primitivePojo.getName());
PrimitivePojo prototypeType2 = new PrimitivePojo(primitivePojo.getId(), primitivePojo.getName());
PrimitivePojo prototypeType3 = new PrimitivePojo(primitivePojo.getId(), primitivePojo.getName());
PrimitivePojo prototypeType4 = new PrimitivePojo(primitivePojo.getId(), primitivePojo.getName());
PrimitivePojo prototypeType5 = new PrimitivePojo(primitivePojo.getId(), primitivePojo.getName());
}
}

优缺点分析:

优点:理解容易

缺点:后期增加属性的时候,需要改动代码,且增加一个必须改动拷贝类的代码,违法了opc原则

浅copy:

需要拷贝的类

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ShallowPojo implements Cloneable {

    private String id;

    private String name;

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

运行拷贝的类

public class Shallow {

    public static void main(String[] args) throws CloneNotSupportedException {
        ShallowPojo shallowPojo = new ShallowPojo("1", "张三");

        System.out.println(shallowPojo);

        ShallowPojo shallowPojo1 = (ShallowPojo) shallowPojo.clone();
        ShallowPojo shallowPojo2 = (ShallowPojo) shallowPojo.clone();
        ShallowPojo shallowPojo3 = (ShallowPojo) shallowPojo.clone();
        ShallowPojo shallowPojo4 = (ShallowPojo) shallowPojo.clone();
        ShallowPojo shallowPojo5 = (ShallowPojo) shallowPojo.clone();

        System.out.println(shallowPojo1);
        System.out.println(shallowPojo2);
        System.out.println(shallowPojo3);
        System.out.println(shallowPojo4);
        System.out.println(shallowPojo5);
    }

}

只能对基础属性以及字符串类型进行copy  

深拷贝:

测试浅拷贝的方式 雷属性的hash一致即为浅copy

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ShallowCopyPojo implements Cloneable {

    private String id;

    private String name;

    private ShallowPojo shallowPojo;

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

运行拷贝的类 

public class DeepMain {

    public static void main(String[] args) throws CloneNotSupportedException {
        // 测试浅拷贝  存在对象属性的情况下 只是引用了地址 没有进行深拷贝
        ShallowCopyPojo shallowCopyPojo = new ShallowCopyPojo("1", "张三", new ShallowPojo("2", "lisi"));
        System.out.println("id: " + shallowCopyPojo.getId() + ", name: " + shallowCopyPojo.getName() + ",shallowPojo hash:" + shallowCopyPojo.getShallowPojo().hashCode());
        ShallowCopyPojo shallowCopyPojo1 = (ShallowCopyPojo) shallowCopyPojo.clone();
        System.out.println("id: " + shallowCopyPojo1.getId() + ", name: " + shallowCopyPojo1.getName() + ",shallowPojo hash:" + shallowCopyPojo1.getShallowPojo().hashCode());
    }
}

深拷贝方式1 (不推荐使用)

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class DeepCopyPojo1 implements Cloneable {

    private String id;

    private String name;

    private DeepCopyPojoA deepCopyPojoA;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        DeepCopyPojo1 result = (DeepCopyPojo1)super.clone();
        result.setDeepCopyPojoA((DeepCopyPojoA) result.getDeepCopyPojoA().clone());
        return result;
    }

}

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
class DeepCopyPojoA implements Cloneable {
    private String id;
    private String name;

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

运行拷贝的类

public class DeepMain {

    public static void main(String[] args) throws CloneNotSupportedException {
        // 深拷贝方式1
        DeepCopyPojo1 deepCopyPojo1 = new DeepCopyPojo1("1", "张三", new DeepCopyPojoA("2", "李四"));
        System.out.println("id: " + deepCopyPojo1.getId() + ", name: " + deepCopyPojo1.getName() + ",shallowPojo hash:" + deepCopyPojo1.getDeepCopyPojoA().hashCode());

        DeepCopyPojo1 deepCopyPojoA = (DeepCopyPojo1) deepCopyPojo1.clone();
        System.out.println("id: " + deepCopyPojoA.getId() + ", name: " + deepCopyPojoA.getName() + ",shallowPojo hash:" + deepCopyPojoA.getDeepCopyPojoA().hashCode());
    }
}

深拷贝方式2(推荐使用)

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class DeepCopyPojo2 implements Cloneable, Serializable {

    private String id;

    private String name;

    private DeepCopyPojoB deepCopyPojoB;

    public DeepCopyPojo2 deepClone() {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;

        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);
            byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            return (DeepCopyPojo2) objectInputStream.readObject();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (Objects.nonNull(objectInputStream)) {
                    objectInputStream.close();
                }
                if (Objects.nonNull(byteArrayInputStream)) {
                    byteArrayInputStream.close();
                }
                if (Objects.nonNull(objectOutputStream)) {
                    objectOutputStream.close();
                }
                if (Objects.nonNull(byteArrayOutputStream)) {
                    byteArrayOutputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
class DeepCopyPojoB implements Serializable {
    private String id;
    private String name;

}

运行拷贝的类

public class DeepMain {

    public static void main(String[] args) throws CloneNotSupportedException {
        // 测试浅拷贝  存在对象属性的情况下 只是引用了地址 没有进行深拷贝
        ShallowCopyPojo shallowCopyPojo = new ShallowCopyPojo("1", "张三", new ShallowPojo("2", "lisi"));
        System.out.println("id: " + shallowCopyPojo.getId() + ", name: " + shallowCopyPojo.getName() + ",shallowPojo hash:" + shallowCopyPojo.getShallowPojo().hashCode());
        ShallowCopyPojo shallowCopyPojo1 = (ShallowCopyPojo) shallowCopyPojo.clone();
        System.out.println("id: " + shallowCopyPojo1.getId() + ", name: " + shallowCopyPojo1.getName() + ",shallowPojo hash:" + shallowCopyPojo1.getShallowPojo().hashCode());

        // 深拷贝方式1
        DeepCopyPojo1 deepCopyPojo1 = new DeepCopyPojo1("1", "张三", new DeepCopyPojoA("2", "李四"));
        System.out.println("id: " + deepCopyPojo1.getId() + ", name: " + deepCopyPojo1.getName() + ",shallowPojo hash:" + deepCopyPojo1.getDeepCopyPojoA().hashCode());

        DeepCopyPojo1 deepCopyPojoA = (DeepCopyPojo1) deepCopyPojo1.clone();
        System.out.println("id: " + deepCopyPojoA.getId() + ", name: " + deepCopyPojoA.getName() + ",shallowPojo hash:" + deepCopyPojoA.getDeepCopyPojoA().hashCode());

        // 深拷贝方式2 推荐使用
        DeepCopyPojo2 deepCopyPojo2 = new DeepCopyPojo2("1", "张三", new DeepCopyPojoB("2", "李四"));
        System.out.println("id: " + deepCopyPojo2.getId() + ", name: " + deepCopyPojo2.getName() + ",shallowPojo hash:" + deepCopyPojo2.getDeepCopyPojoB().hashCode());

        DeepCopyPojo2 deepCopyPojoB = deepCopyPojo2.deepClone();
        System.out.println("id: " + deepCopyPojoB.getId() + ", name: " + deepCopyPojoB.getName() + ",shallowPojo hash:" + deepCopyPojoB.getDeepCopyPojoB().hashCode());

    }
}