设计模式之原型模式


前言

大家好,我是练习两年半的Java练习生,最近阅读了《深入浅出设计模式(中文版)》,学习了各种设计模式,所以想出一个专栏和大家分享一下!
如果大家觉得文章还可以,欢迎关注点赞!后续还会陆续更新!!


一、定义

用原型实例指定创建对象种类,并通过拷贝原型创建新的对象
原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即对象.clone()

二、类图

image.png

三、应用

3.1 需求

3.2 分析

3.3 实现

假设我们需要克隆一只羊,那么我们将🐏这个类实现Cloneable接口,然后实现clone方法。(这里调用的是Object的clone()的话,属于浅拷贝)

public class Sheep implements Cloneable {
    private String name;
    private Integer age;
    private String color;

    public Sheep(String name, Integer age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

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

    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sheep;
    }
}

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("Tom", 1, "白色");
        for (int i = 0; i < 10; i++) {
            Sheep sheep1 = (Sheep) sheep.clone();
            System.out.println(sheep1);
        }
    }
}

四、问题

深拷贝和浅拷贝

浅拷贝

浅拷贝是指将一个对象复制到另一个对象中,复制后的对象和原始对象共享同一块内存,即复制后的对象是原始对象的一个副本,但是它们共享同一块内存空间。在 Java 中,可以通过实现 Cloneable 接口和重写 Object 类中的 clone() 方法来实现浅拷贝。

深拷贝

深拷贝是指将一个对象复制到另一个对象中,复制后的对象和原始对象不共享同一块内存,即复制后的对象是原始对象的一个完全独立的副本。在 Java 中,可以通过实现 Serializable 接口和使用序列化和反序列化来实现深拷贝。
我们定义了一个 Student 类,并实现了 Serializable 接口,通过序列化和反序列化来实现深拷贝。在测试代码中,我们创建了一个 Student 对象 s1,然后将它进行深拷贝得到一个新的对象 s2,最后修改 s2 的属性,发现 s1 的属性没有发生变化,说明 s1 和 s2 是两个完全独立的对象。

import java.io.*;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Object deepClone() throws IOException, ClassNotFoundException {
        // 将对象写入流中
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 将对象从流中读出来
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }

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

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student s1 = new Student("张三", 18);
        Student s2 = (Student) s1.deepClone();

        System.out.println("s1:" + s1.getName() + "," + s1.getAge()); // 输出:s1:张三,18
        System.out.println("s2:" + s2.getName() + "," + s2.getAge()); // 输出:s2:张三,18

        s2.setName("李四");
        s2.setAge(20);

        System.out.println("s1:" + s1.getName() + "," + s1.getAge()); // 输出:s1:张三,18
        System.out.println("s2:" + s2.getName() + "," + s2.getAge()); // 输出:s2:李四,20
    }
}


五、总结

以上就是今天要讲的内容,本文介绍了设计模式原型模式,主要就是实现clone()方法,注意深拷贝和浅拷贝问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而无需通过显式的实例化过程。原型模式通过克隆(clone)已有对象来创建新对象,从而避免了使用传统的构造函数创建对象的开销。 在C++中,原型模式可以通过实现一个可克隆接口(通常称为原型接口)来实现。这个接口通常包含一个克隆方法,用于复制当前对象并返回一个新的副本。派生类可以实现这个接口来定义自己的克隆逻辑。 以下是原型模式的一般实现步骤: 1. 创建一个原型接口(或基类): ``` class Prototype { public: virtual Prototype* clone() const = 0; virtual void setAttributes(...) = 0; virtual void print() const = 0; }; ``` 2. 实现原型接口的具体类(或派生类): ``` class ConcretePrototype : public Prototype { private: // 在派生类中定义特定的属性 // ... public: Prototype* clone() const override { return new ConcretePrototype(*this); } void setAttributes(...) override { // 设置属性值 } void print() const override { // 打印属性值 } }; ``` 3. 在客户端代码中使用原型模式: ``` Prototype* original = new ConcretePrototype(); original->setAttributes(...); Prototype* clone = original->clone(); clone->print(); delete original; delete clone; ``` 通过使用原型模式,我们可以避免在每次创建对象时重复执行初始化的过程,提高了对象的创建效率。此外,原型模式还允许我们在运行时动态地添加或删除对象的属性,并通过克隆来创建新对象。 需要注意的是,在实现原型类时,需要确保所有成员变量都能正确地被拷贝(或克隆)。有时候可能需要自定义拷贝构造函数和赋值运算符来实现深拷贝,以避免浅拷贝带来的问题。 总结起来,原型模式通过克隆已有对象来创建新对象,提供了一种简单且灵活的对象创建方式。它适用于那些对象的创建过程比较复杂或开销较大的情况下。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值