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

    介绍


    原型模式就是对象的copy。在堆中已经有了对象,我们通过克隆的方式复制一份一模一样的对象出来,这就是原型模式。因为只是内存的copy问题, 这样的话省去了创建一个对象的时间。与new不同的地方就是,通过new的方式创建的对象属性采用的是默认值。克隆出来的对象属性值完全和原型对象相同,并且克隆出来的对象发生变化一般不会影响原型对象。

    实现方式


    实现Cloneable接口和clone方法

    示例


    • 示例一

    实现Cloneable接口(其实不用真的实现,这里只是给编译器一个暗示,说明该类可以被克隆)。重写clone方法,该方法是Object中的方法,涉及到内存copy,我们只需要调用父类的clone方法即可。

    package com.dy.xidian;
    
    import java.util.Date;
    
    public class Sheep implements Cloneable {
        private String sname;
        private Date birthday;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        public Sheep(String sname, Date birthday) {
            super();
            this.sname = sname;
            this.birthday = birthday;
        }
    
        public String getSname() {
            return sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
    }

     测试类

    package com.dy.xidian;
    
    import java.sql.Date;
    
    public class Clinet {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Sheep s1 = new Sheep("羊", new Date(123456789L));
            // 打印原羊的信息
            System.out.println("----原羊-----");
            System.out.println(s1);
            System.out.println(s1.getSname());
            System.out.println(s1.getBirthday());
    
            // clone出一个新对象
            Sheep s2 = (Sheep) s1.clone();
            // 打印克隆羊信息
            System.out.println("------克隆羊------");
            System.out.println(s2);
            System.out.println(s2.getSname());
            System.out.println(s2.getBirthday());
            // 更改克隆羊属性
            s2.setSname("克隆羊");
            s2.setBirthday(new Date(1234565433L));
            System.out.println("-----对比------");
            System.out.println("原羊:" + s1.getSname());
            System.out.println("克隆羊:" + s2.getSname());
            System.out.println("克隆羊:" + s2.getBirthday());
        }
    
    }
    • 示例二
    package com.dy.xidian;
    
    import java.sql.Date;
    
    public class Clinet {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Date d = new Date(123456789L);
            Sheep s1 = new Sheep("羊", d);
            // 打印原羊的信息
            System.out.println("----原羊-----");
            System.out.println(s1);
            System.out.println(s1.getSname());
            System.out.println(s1.getBirthday());
    
            // clone出一个新对象
            Sheep s2 = (Sheep) s1.clone();
            // 打印克隆羊信息
            System.out.println("------克隆羊------");
            System.out.println(s2);
            System.out.println(s2.getSname());
            System.out.println(s2.getBirthday());
            // 更改原羊属性
            d.setDate(123456789);
            System.out.println("-----对比------");
            System.out.println("原羊:" + s1.getBirthday());
            System.out.println("克隆羊:" + s2.getBirthday());
        }
    
    }

     

    可以发现当我们修改了data的值后原型和克隆的对象的值都同时发生了变化。这是因为在clone的时候,属性是完全copy。原羊的birtyday属性指向d对象,那么copy出来的birthday属性也应指向相同的对象。当d对象发生改变的时候,这两个属性的值都发生了变化。这就是所谓的浅copy。

    深克隆技术


     

    深克隆需要对属性也进行克隆

    package com.dy.xidian;
    
    import java.util.Date;
    
    public class Sheep implements Cloneable {
        private String sname;
        private Date birthday;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Sheep s = (Sheep) super.clone();
            s.birthday = (Date) this.birthday.clone();
            return s;
        }
    
        public Sheep(String sname, Date birthday) {
            super();
            this.sname = sname;
            this.birthday = birthday;
        }
    
        public String getSname() {
            return sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    }

    通过反序列化实现深克隆

    package com.dy.xidian;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.sql.Date;
    
    public class Clinet {
    
        public static void main(String[] args) throws CloneNotSupportedException,
                IOException, ClassNotFoundException {
            Date d = new Date(123456789L);
            Sheep s1 = new Sheep("羊", d);
            // 打印原羊的信息
            System.out.println("----原羊-----");
            System.out.println(s1);
            System.out.println(s1.getSname());
            System.out.println(s1.getBirthday());
    
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(s1);
            byte[] bytes = bos.toByteArray();
    
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            Sheep s2 = (Sheep) ois.readObject();
    
            System.out.println("----克隆羊-----");
            System.out.println(s2);
            System.out.println(s2.getSname());
            System.out.println(s2.getBirthday());
    
            d.setDate(1784567658);
            System.out.println("------对比------");
            System.out.println("原羊: " + s1.getBirthday());
            System.out.println("克隆羊: " + s2.getBirthday());
        }
    
    }

  • 相关阅读:
    Java版AES-CBC-CMAC加密
    并发编程(十九):并发编程实践
    并发编程(十八):ScheduledThreadPoolExcutor和FutureTask
    并发编程(十七):Excutor与ThreadPoolExcutor
    并发编程(十六):线程池概述
    并发编程(十五):Java并发工具类
    并发编程(十四):原子操作类
    并发编程(十三):Fork-Join框架
    并发编程(十二):阻塞队列
    并发编程(十一):非阻塞队列ConcurrentLinkedQueue
  • 原文地址:https://www.cnblogs.com/xidongyu/p/5627378.html
Copyright © 2011-2022 走看看