• 设计模式-原型模式


    1、原型模式简介

    定义:属于创建型模式,用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象,这种方式创建对象非常高效,根本无须知道对象创建的细节

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

    解决问题:运行期建立和删除实例

    优点:性能提高

        逃避构造函数的约束

    缺点:需要为每一个类都配置一个 clone 方法

       clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。

       当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦

    说明:原型模式的克隆分为两种,一种叫深克隆,一种叫浅克隆

    2、浅克隆

    定义:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址

    实现:必须得实现实现 Cloneable 接口,只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化

    //原型类
    public class User {
        private String name;
        private int date;
        private int age;
        public void setName(String name) {
            this.name = name;
        }
        public void setDate(int date) {
            this.date = date;
        }
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getDate() {
            return date;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return getName()+"&&"+getDate()+"&&"+getAge();
        }
    }
    
    //具体原型类
    public class CloneablePrototype implements Cloneable {
        private User user = new User();
        public CloneablePrototype(){
            user.setAge(25);
            user.setDate(1995);
            user.setName("CC");
            System.out.println("具体原型创建成功");
        }
        public Object clone() throws CloneNotSupportedException {
            System.out.println("具体原型复制成功");
            return (CloneablePrototype)super.clone();
        }
        public User show(){
            return user;
        }
    
    }
    
    //测试方法
    public static void main(String[] args) throws CloneNotSupportedException {
            CloneablePrototype cloneablePrototype1 = new CloneablePrototype();
            CloneablePrototype cloneablePrototype2 = (CloneablePrototype) cloneablePrototype1.clone();
            System.out.println("clone1:"+cloneablePrototype1.show().toString());
            System.out.println("clone2:"+cloneablePrototype2.show().toString());
            System.out.println(cloneablePrototype1 == cloneablePrototype2);
            System.out.println("===========================");
            cloneablePrototype2.show().setAge(30);
            System.out.println("clone1:"+cloneablePrototype1.show().toString());
            System.out.println("clone2:"+cloneablePrototype2.show().toString());
            System.out.println(cloneablePrototype1 == cloneablePrototype2);
    
    }
    //测试结果
    具体原型创建成功
    具体原型复制成功
    clone1:CC&&1995&&25
    clone2:CC&&1995&&25
    false
    ===========================
    clone1:CC&&1995&&30
    clone2:CC&&1995&&30
    false

    3、深克隆

    定义:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址

    实现:实现 Serializable 接口,通过字节流来对数据进行复制

    //原型类,实现Serializable接口
    public class User extends Object implements Serializable {
        private static final long serialVersionUID = 1L;
        private String name;
        private int date;
        private int age;
        public void setName(String name) {
            this.name = name;
        }
        public void setDate(int date) {
            this.date = date;
        }
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getDate() {
            return date;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return getName()+"&&"+getDate()+"&&"+getAge();
        }
    }
    
    //具体原型类
    public class SerializablePrototype implements Serializable {
    
        private User user = new User();
        public SerializablePrototype(){
            user.setAge(21);
            user.setName("NN");
            user.setDate(1998);
            System.out.println("具体原型创建成功");
        }
        public User show(){
            return user;
        }
        public SerializablePrototype sClone(SerializablePrototype serializablePrototype){
            try(ByteArrayOutputStream bOut = new ByteArrayOutputStream();
                ObjectOutputStream oOut = new ObjectOutputStream(bOut)){
                //oOut对象中指向写入数据存储的内存地址与bOut对象中指向数据存储的内存地址是一样的
                oOut.writeObject(serializablePrototype);
                try(ByteArrayInputStream bIn= new ByteArrayInputStream(bOut.toByteArray());
                    ObjectInputStream oIn = new ObjectInputStream(bIn)){
                    Object o = oIn.readObject();
                    System.out.println("具体原型复制成功");
                    return (SerializablePrototype) o;
                }catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return  null;
        }
    }
    
    //测试方法
    public static void main(String[] args) throws CloneNotSupportedException {
            SerializablePrototype s1 = new SerializablePrototype();
            SerializablePrototype s2 = s1.sClone(s1);
            System.out.println(s1.show().toString());
            System.out.println(s2.show().toString());
            System.out.println(s1 == s2);
            System.out.println("============================");
            s2.show().setName("QQ");
            System.out.println(s1.show().toString());
            System.out.println(s2.show().toString());
            System.out.println(s1 == s2);
    }
    //测试结果
    具体原型创建成功
    具体原型复制成功
    NN&&1998&&21
    NN&&1998&&21
    false
    ============================
    NN&&1998&&21
    QQ&&1998&&21
    false
    
    由此可见,s2改变之后s1的不变,说明通过字节流将s1对象指向的实际内存地址中的数据复制到另一块实际内存中,s2指向的这块新的内存地址
  • 相关阅读:
    零基础入门深度学习(1)
    RxJava 复杂场景 Schedulers调度
    Kotlin 学习
    Cordova CrossWalk
    Android Studio工程导入另一个工程作为lib
    Android 数据存储相关
    Android Activity 生命周期中onStart()和onResume()的区别
    反省与规划
    Android 依赖注入 ButterKnife 基本使用
    Android Socket 相关
  • 原文地址:https://www.cnblogs.com/carblack/p/13749579.html
Copyright © 2020-2023  润新知