探索设计模式:原型模式

设计模式之原型模式

    • [🧐1. 概念](#🧐1. 概念)
    • [🎯2. 原型模式的作用](#🎯2. 原型模式的作用)
    • [📦3. 实现](#📦3. 实现)
      • [1. 定义原型接口](#1. 定义原型接口)
      • [2. 定义具体的原型类](#2. 定义具体的原型类)
      • [3. 定义客户端](#3. 定义客户端)
      • [4. 结果](#4. 结果)
    • [📰 4. 应用场景](#📰 4. 应用场景)
    • [🔍5. 深拷贝和浅拷贝](#🔍5. 深拷贝和浅拷贝)

在面向对象编程中,设计模式是一种通用的解决方案,用于解决软件设计过程中常见的问题。原型模式(Prototype Pattern)作为创建型设计模式的一员,旨在通过复制现有对象来创建新对象,而非通过常规的构造函数。这种模式不仅简化了对象的创建过程,而且在特定情况下还能显著提升性能。

🧐1. 概念


原型模式允许客户端复制一个已存在的对象,而不是通过常规的构造器创建一个新的实例。这种方法的主要优点在于,如果对象的创建成本很高(例如,初始化过程复杂、需要从数据库加载大量数据等),那么通过复制现有对象的方式可以有效减少资源消耗,提高系统的整体性能。

  1. Prototype抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。
  2. ConcretePrototype具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
  3. Client客户端类 ):通过调用 clone() 方法来创建新的对象,并展示了原始对象与克隆对象之间的独立性。

🎯2. 原型模式的作用

  1. 简化对象创建:通过复制现有的对象,可以避免复杂的构造过程,尤其是当对象的初始化需要进行大量的计算或资源分配时。
  2. 提高性能:对于那些创建成本高得对象,使用原型模式可以显著减少内存消耗和处理时间。
  3. 增加系统灵活性:通过修改原型对象得属性,可以快速生成不同状态的新对象,这比通过继承来实现更加灵活。

📦3. 实现


实现原型模式的核心在于定义一个原型接口,该接口包含一个用于复制自身的克隆方法。在不同的编程语言中,实现方式可能会有所不同,但基本思路是一致的。

1. 定义原型接口


java 复制代码
public interface Prototype extends Cloneable {
    Prototype clone();
}

此处的 Cloneable 接口是一个标记接口,表示该类可以被克隆。

类似的标记接口还有

  • Serializable:用于标记一个类的对象可以被序列化和反序列化。
  • RandomAccess:用于标记一个列表支持随机访问,即通过索引直接访问元素吗,而不是遍历。
  • Remote:用于远程方法调用,标记一个类支持远程方法调用。

2. 定义具体的原型类


java 复制代码
public class ConcretePrototype implements Prototype {

    private String attribute;

    public ConcretePrototype(String attribute) {
        this.attribute = attribute;
    }


    @Override
    public Prototype clone() {
        try {
            return (ConcretePrototype) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError("Cannot clone.", e);
        }
    }

    public String getAttribute() {
        return attribute;
    }

    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }

}

3. 定义客户端


java 复制代码
public class Client {

    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype("Initial Value");
        ConcretePrototype clonedPrototype = (ConcretePrototype) prototype.clone();
        System.out.println("Original Attribute: " + prototype.getAttribute());
        System.out.println("Cloned Attribute: " + clonedPrototype.getAttribute());

        clonedPrototype.setAttribute("Modified Value");
        System.out.println("After Modification:");
        System.out.println("Original Attribute: " + prototype.getAttribute());
        System.out.println("Cloned Attribute: " + clonedPrototype.getAttribute());
    }
}

4. 结果


在这个示例中,ConcretePrototype 类实现了 Prototype 接口,并提供了具体的 clone() 方法实现。客户端代码展示了如何通过调用 clone() 方法来创建新的对象,并展示了原始对象与克隆对象之间的独立性。

📰 4. 应用场景


  1. 对象创建成本高:当对象的创建对象过程非常复杂或耗时,例如需要从网络加载数据、执行复炸的算法等,使用原型模式可以通过复制现有对象来节省时间和资源。
  2. 避免复杂的构造过程:如果对象的创建涉及到复杂的初始化步骤,使用原型模式可以简化这些步骤,通过复制已有对象来快速生成新的对象。
  3. 动态对象创建:在某些情况下,程序需要根据用户的输入或其他条件动态地创建对象。原型模式提供了一种灵活的方式来满足这种需求,无需预先定义所有的对象类型。
  4. 实际项目当中使用原型模式,实现 Cloneable 接口并重写 clone() 方法。或者编写自己的特有的原型类 Prototype ,然后实现 Prototypeclone() 方法。

🔍5. 深拷贝和浅拷贝


在讨论原型模式时,深拷贝浅拷贝 是一个不可忽视的话题。浅拷贝 只会复制对象的基本数据类型和其他对象的引用,而不会递归地复制引用对象本身。相反,深拷贝会递归地复制整个对象树,确保新对象与原有对象完全独立。

Java 中, 默认的 clone() 方法实现的是浅拷贝。如果需要实现深拷贝,通常需要手动编写代码来处理对象中的引用类型属性。例如,可以使用序列化和反序列化的方式来实现深拷贝:

java 复制代码
public class DeepClonePrototype implements Cloneable, Serializable {

    private transient String attribute; // 使用 transient 修饰符表示不参与序列化

    public DeepClonePrototype(String attribute) {
        this.attribute = attribute;
    }
    
    public String getAttribute() {
        return this.attribute;
    }
    
    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }

    @Override
    protected DeepClonePrototype clone() {
        try {
            // 使用序列化和反序列化实现深拷贝
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(this);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            return (DeepClonePrototype) in.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new AssertionError("Cannot clone.", e);
        }
    }

}
相关推荐
海特伟业3 小时前
隧道调频广播覆盖-隧道调频广播无线覆盖系统建设要点、难点分析与解决应对
运维·设计模式
sg_knight3 小时前
设计模式实战:享元模式(Flyweight)
python·设计模式·享元模式·flyweight
Swift社区6 小时前
AI 时代,ArkUI 的设计模式会改变吗?
人工智能·设计模式
数据中穿行6 小时前
访问者设计模式全方位深度解析
设计模式
宁雨桥7 小时前
前端设计模式面试题大全
前端·设计模式
数据中穿行8 小时前
迭代器设计模式全方位深度解析
设计模式
数据中穿行8 小时前
观察者设计模式全方位深度解析
设计模式
程序员Terry8 小时前
别老写重复代码了!模版方法模式一次讲透
java·设计模式
数据中穿行8 小时前
建造者模式全方位深度解析
设计模式
数据中穿行8 小时前
组合设计模式全方位深度解析
设计模式