原型模式_创建型模式

本文介绍了原型模式在对象创建中的应用,详细解析了浅拷贝和深拷贝的区别。通过Java代码示例展示了如何实现Cloneable接口进行浅拷贝,以及如何利用序列化进行深拷贝。原型模式能提高对象创建的效率,但需要注意对引用类型的处理,以避免意外效果。同时,文章提到了原型模式在撤销操作和性能优化上的优势,但也指出其需要修改源代码的缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一种对象创建型模式,使用原型实例指定创建对象的种类。拷贝对象。实际是对Cloneable接口的使用。
该模式也运用到了深拷贝和浅拷贝这个知识点。
核心组成:

  • Prototype: 声明克隆方法的接口,即Cloneable接口,原型模式即为对整个接口的实现,其中实践了深拷贝浅拷贝知识点
  • ConcretePrototype:具体的原型类,实现了克隆接口
  • Client: 原型类克隆而得到的实例

浅拷贝实现 Cloneable,深拷贝是通过实现 Serializable 读取二进制流

浅拷贝
如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制一份给克隆对象;
如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址
​通过覆盖Object类的clone()方法可以实现浅克隆

深拷贝
无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过序列化(Serializable)等方式来实现
原型模式是内存二进制流的拷贝,比new对象性能高很多,使用的时候记得注意是选择浅拷贝还是深拷贝

// 原型对象
public class Person implements Cloneable {
    String name;
    int age;
    
    public Person() {
        System.out.println("---调用构造函数----");
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

}

在这里插入图片描述
在这里插入图片描述
可以看到,在生成person1 和person2的过程中只调用了一次构造方法。即得到了两个对象。
但是如果原型对象包含引用类型时,那么会出现意外的效果。因此需要改造原型类

public class Person implements Cloneable, Serializable {
    String name;
    int age;
    List<String> list;

    public Person() {
        System.out.println("---调用构造函数----");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", list=" + list +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
	// 声明深拷贝方法
    public Person deepClone() {
        // 输出序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);

            // 输入,反序列化
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Person person = (Person) ois.readObject();
            return person;
        } catch (IOException  | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}

总结:

优点
  • 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,可以提高新实例的创建效率
  • 辅助实现撤销操作,使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用恢复到历史状态
缺点
  • 需要为每一个类配备一个克隆方法,对已有的类进行改造时,需要修改源代码,违背了“开闭原则”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值