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

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

    它主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。

    下面我克隆一个类,并修改名字和年龄,看看有什么变化

    package com.taobao.business;
    
    
    /**
     * 原型模式:创建型
     */
    public class Prototype
    {
        public static void main(String[] args) throws Exception
        {
            //先创建一个对象原型
            Person p = new Person("张三",18);
            try {
                Person cloneP = (Person) p.clone();
                System.out.println("原来的:" + p);
                System.out.println("克隆的:" + cloneP);
                cloneP.setName("李四");        //修改名字
                cloneP.ageClass.update();    //修改年龄
                System.out.println("修改后原来的:" + p);
                System.out.println("修改后克隆的:" + cloneP);
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 浅拷贝
     */
    class AgeClass{
        public long age;
        //修改age
        public void update(){
            this.age *= 2;
        }
        @Override
        public String toString() {
            return "年龄:"+age;
        }
    }
    class Person implements Cloneable{
        private String name;
        public AgeClass ageClass = new AgeClass();
        
        public Person(String name, long age) {
            super();
            this.name = name;
            this.ageClass.age = age; 
        }
        //修改name
        public void setName(String name) {
            this.name = name;
        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person person = (Person) super.clone();
            return person;
        }
        @Override
        public String toString() {
            return "姓名:"+name+","+ageClass;
        }
    }

    输出的结果是:

    原来的:姓名:张三,年龄:18
    克隆的:姓名:张三,年龄:18
    修改后原来的:姓名:张三,年龄:36
    修改后克隆的:姓名:李四,年龄:36

    为什么修改了克隆对象后,姓名改变了,但是年龄为什么原来那个对象也改变了?而且我定义的姓名是一个基础类型,而年龄是自定义的类型,这说明浅克隆是不能把复杂类型的值克隆出来的,那么如果解决呢?有人可能会想那把年龄那个类不要做成自定义类型不就可以了吗?但是现实情况可能不是一个年龄类呢?而且是一个其它的复杂类型呢?所以这就要采用深度克隆,把年龄类改成也实现Cloneable接口。

    /**
     * 深拷贝
     */
    class AgeClass implements Cloneable{
        public long age;
        //修改age
        public void update(){
            this.age *= 2;
        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return (AgeClass) super.clone();
        }
        @Override
        public String toString() {
            return "年龄:"+age;
        }
    }

    当然Person类的clone方法也要相应的改一下

        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person person = (Person) super.clone();
            person.ageClass = (AgeClass)ageClass.clone();    //深拷贝
            return person;
        }

    ok,现在运行一下,看看年龄克隆后是的引用还是把值克隆过去了?

    原来的:姓名:张三,年龄:18
    克隆的:姓名:张三,年龄:18
    修改后原来的:姓名:张三,年龄:18
    修改后克隆的:姓名:李四,年龄:36

    可以了!现在的自定义类型也克隆过去了!而且把克隆对象改了,也不会对以前的对象有其它影响。

    但是当这中自定义类型中如果又包含有很多个自定义类型呢?难道把每个类都改成实现Clone接口吗?那是不是太麻烦点了?这样的话,我们可以把对象序列化,当需要的时候再反序列化。

        /**
         * 序列化
         */
        private static Object cloneObject(Object obj) throws Exception{
            //把对象写入字节数组
            ByteArrayOutputStream  byteOut = new ByteArrayOutputStream();  
            ObjectOutputStream out = new ObjectOutputStream(byteOut);  
            out.writeObject(obj); 
            //从字节数组读取出对象
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
            ObjectInputStream in =new ObjectInputStream(byteIn);
            
            return in.readObject();
        }
  • 相关阅读:
    Maven学习笔记:Maven简介
    Maven学习笔记:POM标签大全详解
    Java中引用类型、对象的创建与销毁
    【网络与系统安全】WANNACRY病毒中的加解密技术的应用 20199321
    vim编辑器学习 20199321
    Docker 导出和导入容器
    快速排序
    [3]遍历进程链表找到游戏进程
    AutoCompleteTextView使用demo
    validating & update ctabfolder css
  • 原文地址:https://www.cnblogs.com/hnhcc39/p/2612239.html
Copyright © 2011-2022 走看看