zoukankan      html  css  js  c++  java
  • 原型模式

      原型模式定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

      在JAVA语言中使用原型模式是非常简单的,这是因为Object类当中提供了一个本地方法clone,而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝。

      从原型模式的使用方式不难推断出,原型模式常使用于以下场景:

      1、对象的创建非常复杂,可以使用原型模式快捷的创建对象。
      2、在运行过程中不知道对象的具体类型,可使用原型模式创建一个相同类型的对象,或者在运行过程中动态的获取到一个对象的状态。

      由于clone方法是由虚拟机直接复制内存块执行,所以在速度上比使用new的方式创建对象要快,并且在拷贝对象时不会执行对应类的构造方法。

      提到原型模式,就不得不提浅拷贝和深拷贝。浅拷贝是指将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。深拷贝将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制。

      下面我们来看一个浅拷贝的例子

    package prototype;
    
    public class Student {
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        
    }
    package prototype;
    
    public class Family implements Cloneable{
    
        private String address;
        private Student student;
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public Student getStudent() {
            return student;
        }
        public void setStudent(Student student) {
            this.student = student;
        }
        public Family clone() {
            Object obj = null;
            try {
                obj = super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return (Family) obj;
        }
    }

      编写测试代码,结果如下:

      可以看到我们copy得来的对象fa2中持有的Student实例和fa中的是一个,所以当我们对fa2中student对象进行修改时,会影响到原来的fa,那么如何实现深拷贝呢?有两种方式。

      1、要实现深度拷贝,则需要将实现了Cloneable接口并重写了clone方法的类中,所有的引用类型也全部实现Cloneable接口并重写clone方法,而且需要将引用类型的属性全部拷贝一遍。

      修改Student和Fimaly类如下

    package prototype;
    
    public class Student implements Cloneable{
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public Student clone() {
            Object obj = null;
            try {
                obj = super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return (Student) obj;
        }
    }
    package prototype;
    
    public class Family implements Cloneable{
    
        private String address;
        private Student student;
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public Student getStudent() {
            return student;
        }
        public void setStudent(Student student) {
            this.student = student;
        }
        public Family clone() {
            Object obj = null;
            try {
                obj = super.clone();
                ((Family)obj).setStudent(this.student.clone());
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return (Family) obj;
        }
    }

      执行测试代码如下:

      2、利用序列化,我们的目标类要实现Serializable接口

      修改Student和Fimaly类如下

    package prototype;
    
    import java.io.Serializable;
    
    public class Student implements Serializable{
        private static final long serialVersionUID = -3865833738045253326L;
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    }
    package prototype;
    
    import java.io.Serializable;
    
    public class Family implements Serializable{
    
        private static final long serialVersionUID = 7498435126824884787L;
        private String address;
        private Student student;
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public Student getStudent() {
            return student;
        }
        public void setStudent(Student student) {
            this.student = student;
        }
    }

      测试类

    package prototype;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    public class Client2 {
    
        public static Family depCopy(Family fa) {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            try {
                ObjectOutputStream out = new ObjectOutputStream(byteOut);
                out.writeObject(fa);
     
                ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
                ObjectInputStream inStream = new ObjectInputStream(byteIn);
                Family fa2 = (Family) inStream.readObject();
                return fa2;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        public static void main(String[] args) {
            Student stu = new Student("张三", 12);
            Family fa = new Family();
            fa.setAddress("北京");
            fa.setStudent(stu);
            Family fa2 = depCopy(fa);
            System.out.println(fa2.getStudent() == fa.getStudent());
        }
    }

      结果自然是false,就不再贴出了。

      

  • 相关阅读:
    kettle安装及初步使用
    Datax初步使用
    可修改性及其实现战术(hot words)
    淘宝网的六个质量属性
    python数据可视化笔记---——matplotlib.pyplot()
    Linux虚拟环境virtualevn
    deepin安装虚拟环境virtualenv
    python面试题-web后端
    rabbitmq和redis用作消息队列的区别
    nginx配置项概括说明
  • 原文地址:https://www.cnblogs.com/hhhshct/p/10027936.html
Copyright © 2011-2022 走看看