原型模式——NWU_LK

原型模式

基本概念

原型模式是指用原型实例指定创建的种类,并且通过拷贝这些原型,创建新的对象。原型模式是一种创建型设计模式,允许一个对象创建另一个可定制的对象,无需知道创建的细节。
在这里插入图片描述
如图所示,首先我们可以看到一共有三个角色:

  1. 客户(Client)角色:客户类提出创建对象的请求;也就是我们用户使用复制粘贴的功能。

  2. 抽象原型(Prototype)角色:此角色定义了的具体原型类所需的实现的方法。也就是定义一个文件,说明一下它有被克隆复制的功能。

  3. 具体原型(Concrete Prototype)角色:实现抽象原型角色的克隆接口。就是我们的文件实现了可以被复制的功能。

我们会发现其实原型模式的核心就是Prototype(抽象原型),他需要继承Cloneable接口,并且重写Object类中的clone方法才能有复制粘贴的功能。

拷贝的分类

既然我们知道原型模式的核心就是拷贝对象,那么我们能拷贝一个对象实例的什么内容呢?这就要区分深拷贝和浅拷贝之分了。

  • 浅拷贝:我们只拷贝对象中的基本数据类型(8种),对于数组、容器、引用对象等都不会拷贝。比如该段代码输出的结果为false和true,duoli对象和clone对象不是同一个对象,但是其friend都指向同一个对象。

    //创建引用对象Dog类
    class Dog{
        public String name;
        public int age;
        public Dog(String name,int age){
            this.name=name;
            this.age=age;
        }
    }
    class Sheep implements Cloneable{
        public String name;
        public int age;
        public Dog friend;
        public Sheep(String name,int age){
            this.name=name;
            this.age=age;
        }
        @Override
        protected Sheep clone(){
            Sheep sheep=null;
            try {
                sheep = (Sheep)super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return sheep;
        }
    }
    public void test() throws CloneNotSupportedException {
        Sheep duoli=new Sheep("duoli",2);
        duoli.friend= new Dog("dahuang",2);
        Sheep clone = duoli.clone();
        System.out.println(clone==duoli);
        System.out.println(clone.friend==duoli.friend);
    }
    
  • 深拷贝:不仅能拷贝基本数据类型,还能拷贝那些数组、容器、引用对象等,实现方式可以是引用对象实现Cloneable接口,也可是序列化接口。

  1. 实现Cloneable接口,让Sheep中的引用对象实现克隆接口,然后在Sheep类的Clone方法中,对其引用属性也进行克隆。

    class Dog implements Cloneable{
        public String name;
        public int age;
        public Dog(String name,int age){
            this.name=name;
            this.age=age;
        }
        @Override
        protected Dog clone(){
            Dog dog=null;
            try {
                dog = (Dog)super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return dog;
        }
    }
    class Sheep implements Cloneable{
        public String name;
        public int age;
        public Dog friend;
        public Sheep(String name,int age){
            this.name=name;
            this.age=age;
        }
        @Override
        protected Sheep clone(){
            Sheep sheep=null;
            try {
                sheep = (Sheep)super.clone();
                sheep.friend=friend.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return sheep;
        }
    }
    
  2. 实现序列化接口

    class Dog implements Serializable{
        public String name;
        public int age;
        public Dog(String name,int age){
            this.name=name;
            this.age=age;
        }
    }
    class Sheep implements Cloneable,Serializable{
        public String name;
        public int age;
        public Dog friend;
        public Sheep(String name,int age){
            this.name=name;
            this.age=age;
        }
        @Override
        protected Sheep clone(){
            ByteArrayOutputStream bos=null;
            ObjectOutputStream oos=null;
            ByteArrayInputStream bis=null;
            ObjectInputStream ois=null;
            try {
                bos=new ByteArrayOutputStream();
                oos=new ObjectOutputStream(bos);
                oos.writeObject(this);
    
                bis=new ByteArrayInputStream(bos.toByteArray());
                ois=new ObjectInputStream(bis);
                return (Sheep)ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    bos.close();
                    oos.close();
                    bis.close();
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }
    
分析原型模式
  • 克隆对象不会调用构造方法。这是因为执行clone方法的时候是直接从内存中去获取数据的,在第一次创建对象的时候就会把数据在内存保留一份,克隆的时候直接调用就好了

  • 访问权限对原型模式无效。原理也很简单,我们是从内存中直接复制的,所以克隆起来也会直接无视,复制相应的内容就好了。

适用场景
  1. 当我们的类初始化需要消耗很多的资源时,就可以使用原型模式,因为我们的克隆不会执行构造方法,避免了初始化占有的时间和空间。
  2. 一个对象被其她对象访问,并且能够修改时,访问权限都无效了,什么都能修改。
JAVA中的使用

Spring创建Bean对象时,有单例模式(singletype)和原型模式(prototype)。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值