设计模式-原型模式的原理和实现

原型模式:

  • 有时候,我们需要一个实例,但是创建这个实例的过程比较复杂,比如构造函数非常的复杂,执行这个构造函数时会消耗较长的时间,但另外一方面,这个构造函数中的一些信息又没有什么变化(也就是说创建第一个实例时初始化信息是这样的,创建第二个实例时初始化信息还是还是这样的),那么直接使用new再创建这样一个实例就显得太昂贵了,此时可以使用克隆,也就是复制,就是通过复制现在已经有了的实例来创建新的实例。

深拷贝与浅拷贝

  • object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝(也称为影子拷贝)。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
  • 对象类的克隆方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝(也称为影子拷贝)。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝.上面clone简历的操作中发现,clone的所有的简历共享同一个Address,这就是因为只是进行了浅拷贝,Address是引用数据类型,没有进行复制。如果要同时复制,需要使用深拷贝实现。上面克隆简历的操作中发现,克隆的所有的简历共享同一个地址,这就是因为只是进行了浅拷贝,Address是引用数据类型,没有进行复制。如果要同时复制,需要使用深拷贝实现.

优点:

  • 使用原型模式创建对象比直接new一个对象在性能上要好的多(一般情况下),因为object类的clone方法是一个本地native方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
  • 简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
  • 底层直接复制,不通过构造方法,也不受权限修饰符的影响。

缺点:

  • 需要为每一个类配置一个克隆方法,而且该克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
  • 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

适用情况:

  • 要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
  • 需要注意的是∶我们可以利用clone方法来实现对象之间的复制,但对于比较复杂的对象(比如对象中包含其他对象,其他对象又包含别的对象…)这样我们必须进行层层深度clone,每个对象需要实现cloneable接口,比较麻烦,此时采用序列化也是一个不错的万法(可以先使用objectOutputStream的writeObject 实现序列化到一个字节数组,不用序列化到硬盘或者网络,再使用objectInputStream的readObject反序列化就生成一个一模一样的对象,不管多么复杂的结构)。
/**
 * 简历类
 * 原型模式的关键点
 * 1.类要实现Cloneable接口
 * 2.重写clone ()方法﹐将protected权限修改为public'返回值建议由0bject改为当前类
 */
public class Resume implements Cloneable{
    private String name;//年龄

    private String sex;//性别

    private int age;//年龄

    private Address address;//地址

    @Override
    public Resume clone() throws CloneNotSupportedException {
        Resume resume =(Resume)super.clone();
        //resume.address=this.address.clone();
        return (Resume)super.clone();
    }

    public Resume() {
    }

    @Override
    public String toString() {
        return "Resume{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Resume(String name, String sex, int age, Address address) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.address = address;
    }
}
/**
 * 地址类
 */
public class Address /*implements Cloneable*/{

    private String city;//城市

    private String disstriot;//区县

    private String street;//街道

    /*@Override
    public Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }*/

    public Address() {
    }

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                ", disstriot='" + disstriot + '\'' +
                ", street='" + street + '\'' +
                '}';
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getDisstriot() {
        return disstriot;
    }

    public void setDisstriot(String disstriot) {
        this.disstriot = disstriot;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public Address(String city, String disstriot, String street) {
        this.city = city;
        this.disstriot = disstriot;
        this.street = street;
    }
}
public class Tset {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address address=new Address("云南省","昭通","巧巧街道");
        Resume resume1 = new Resume("巧巧","女",23,address);
        address.setCity("大理");
        System.out.println(resume1);
        Resume resume2 = resume1.clone();
        System.out.println(resume2);
        Resume resume3 = resume1.clone();
        System.out.println(resume3);
    }
}

以上操作被定义为:浅拷贝 ;打开注释就是深拷贝大家自己动手实现一遍即可掌握

技术的升级迭代只是为了淘汰那些不学习的人!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值