zoukankan      html  css  js  c++  java
  • 原型模式(Prototype Pattern)

      原型模式就是为了对象拷贝的,省掉了堆内存一系列的复杂流程。

      对象拷贝分为深拷贝和浅拷贝

      浅拷贝:将对象中的简单类型和String类型的值进行复制,引用类型复制的只是对象的引用地址

      深拷贝:所有的类型都是直接复制的值,包括引用对象;如果是引用对象,会新创建一个对象,并且引用地址改为该对象。

      原型模式的优点:

        1、根据客户端要求实现动态创建对象,客户端不需要知道对象的创建细节,便于代码的维护和发展

        2、使用原型模式创建对象比直接new一个对象在性能上要好得多,因为Object类的clone方法是一个本地方法,他直接操作内存中的二进制流,特别是复制大对象时,性能差别非常明显。

      使用原型模式时需要注意的点:

        1、使用原型模式复制对象不会调用类的构造方法

        2、在使用时要注意深拷贝和浅拷贝的问题

      浅拷贝代码示例:

    package com.lcl.galaxy.design.pattern.prototype;
    
    import java.io.Serializable;
    
    public class Prototype implements Cloneable, Serializable {
        private static final long serialVersion = 1L;
    
        private String name;
    
        private int age;
    
        private Order order;
    
        public Prototype shallowClone() throws CloneNotSupportedException {
            Prototype prototype = (Prototype) super.clone();
            return prototype;
        }
    }

      浅复制主要的点就是需要对象实现Cloneable接口,该接口没有方法,只是做一个标识,JVM虚拟机看到该标识后,就可以做对象的浅拷贝。至于具体哪个方法做对象复制,自己定义方法名即可,在方法中直接调用super的clone方法即可

      深拷贝代码示例:

    package com.lcl.galaxy.design.pattern.prototype;
    
    
    import java.io.*;
    
    public class Prototype implements Cloneable, Serializable {
        private static final long serialVersion = 1L;
    
        private String name;
    
        private Order order;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setOrder(Order order) {
            this.order = order;
        }
    
        public String getName() {
            return name;
        }
    
        public Order getOrder() {
            return order;
        }public Prototype deepClone() throws IOException, ClassNotFoundException {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
    
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Prototype) ois.readObject();
        }
    }

      深拷贝的代码主要是使用字节流来创建一个新的对象,那么无论是该对象本身还是该对象中的引用对象,都需要实现Serializable序列化接口。

      针对上述浅拷贝和深拷贝,测试代码如下:

    package com.lcl.galaxy.design.pattern;
    
    import com.alibaba.fastjson.JSON;
    import com.lcl.galaxy.design.pattern.builder.Animal;
    import com.lcl.galaxy.design.pattern.builder.AnimalBuilder;
    import com.lcl.galaxy.design.pattern.prototype.Order;
    import com.lcl.galaxy.design.pattern.prototype.Prototype;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.io.IOException;
    
    @Slf4j
    @SpringBootTest
    public class PrototypeTest {
    
        @Test
        public void prototypeShallowCloneTest() throws CloneNotSupportedException {
            Prototype prototype = getPrototype();
            Prototype copyPrototype = prototype.shallowClone();
            print(prototype, copyPrototype);
        }
    
        @Test
        public void prototypeDeepCloneTest() throws IOException, ClassNotFoundException {
            Prototype prototype = getPrototype();
            Prototype copyPrototype = prototype.deepClone();
            print(prototype, copyPrototype);
        }
    
    
        private Prototype getPrototype(){
            Order order = new Order();
            order.setOrderId("1234");
            Prototype prototype = new Prototype();
            prototype.setOrder(order);
            prototype.setName("lcl");
            return prototype;
        }
    
        private void print(Prototype prototype, Prototype copyPrototype){
            log.info("prototype=================={}=================", prototype);
            log.info("copyPrototype=================={}=================", copyPrototype);
            log.info("prototype=================={}=================", JSON.toJSONString(prototype));
            log.info("copyPrototype=================={}=================", JSON.toJSONString(copyPrototype));
            log.info("prototype.getOrder()=================={}=================", prototype.getOrder());
            log.info("copyPrototype.getOrder()=================={}=================", copyPrototype.getOrder());
            log.info("prototype.equals(copyPrototype)=================={}=================", prototype.equals(copyPrototype));
            log.info("prototype.getName().equals(copyPrototype.getName())=================={}=================", prototype.getName().equals(copyPrototype.getName()));
            log.info("prototype.getOrder().equals(copyPrototype.getOrder())=================={}=================", prototype.getOrder().equals(copyPrototype.getOrder()));
            log.info("prototype.getOrder().getOrderId().equals(copyPrototype.getOrder().getOrderId())=================={}=================", prototype.getOrder().getOrderId().equals(copyPrototype.getOrder().getOrderId()));
        }
    
    }

      最终的输出结构,虽然取到的值多一样,但是如果对比Prototype中的Order对象,浅拷贝和深拷贝则是两种结果:浅拷贝为true,即引用对象为同一个对象;深拷贝为false,即引用对象不是同一个对象。

  • 相关阅读:
    安装触摸板驱动导致系统无法开机
    TensorBoard的使用
    TensorFlow 编程基础
    在Anaconda3下安装(CPU版)TensorFlow(清华镜像源)
    C 程序
    CodeBlocks 断点调试
    数字图像处理之复原处理
    数字图像处理之频域图像增强
    数字图像处理之傅里叶变换
    算法导论中的四种基本排序
  • 原文地址:https://www.cnblogs.com/liconglong/p/14171657.html
Copyright © 2011-2022 走看看