设计模式-原型模式

什么是原型模式

     原型模式是一种创建型设计模式,用于在不直接使用new运算符创建对象的情况下,通过复制现有对象来生成新对象。它允许我们通过复制现有对象的属性和方法来创建新的对象,而无需了解对象的具体实现细节。原型模式使用原型实例来创建新的对象,通过克隆原型对象来创建新的对象,而不是通过创建新的类或实例化模板类。

在原型模式中,原型对象是被复制的对象,在创建新对象时,只需要将原型对象复制一份即可得到新的对象。这种复制可以是浅复制,即只复制对象的基本数据类型属性或引用类型属性的引用;也可以是深复制,即复制对象的所有属性和子对象。

原型模式适用于以下情况:

  • 当对象的创建过程较为复杂,且创建过程中涉及到的对象类型不固定时,可以使用原型模式来简化对象的创建过程。
  • 当需要创建的对象内部结构相对稳定,只是属性值不同,或者对象之间存在一些类似的属性和方法时,可以使用原型模式来复用已有对象的属性和方法。
  • 当需要创建大量相似的对象时,使用原型模式可以大大提高对象的创建效率,避免重复创建相似的对象。

使用原型模式可以带来很多好处,如简化对象的创建过程、提高对象的复用性、减少重复创建对象的开销等。但在使用原型模式时需要注意,克隆对象可能会引入性能问题,需要根据具体情况进行评估和优化。

原型模式的应用场景

  1. 当创建一个对象的过程比较复杂或者耗时时,可以使用原型模式来复制一个已有的对象,然后进行修改和定制,避免重新创建对象的过程。

  2. 当需要创建的对象的种类较多,而且这些对象之间的区别仅在于其属性的值时,可以使用原型模式来通过复制一个已有的对象来创建新的对象,然后再进行属性的修改。

  3. 当需要创建一个对象的多个实例,而且这些实例之间相互独立,可以使用原型模式来利用已有的对象作为原型,通过复制来创建新的对象。

  4. 当需要动态地添加或删除对象时,可以使用原型模式来通过复制一个已有的对象来创建新的对象,然后再进行动态的增加或删除。

原型模式的使用方式

  1. 创建一个原型接口或抽象类,定义复制自身的方法。
  2. 创建需要复制的具体原型类,实现原型接口或继承抽象类。
  3. 在原型类中实现复制自身的方法,该方法会创建并返回一个新的对象。
  4. 在客户端代码中,创建一个原型对象,并调用复制方法来创建新的对象。

原型模式分为浅复制和深复制

浅复制是指在复制对象时,只复制对象本身的值,而不复制对象包含的引用类型的成员。这意味着复制的对象和原始对象共享同一个引用类型的成员,当其中一个对象修改了引用类型的成员时,另一个对象也会受到影响。

深复制是指在复制对象时,不仅复制对象本身的值,还复制对象包含的引用类型的成员。这意味着复制的对象和原始对象拥有各自独立的引用类型的成员,彼此之间互不影响。

在使用原型模式时,需要根据具体情况选择浅复制还是深复制。如果对象包含的引用类型成员是不可变的,或者不需要对复制后的对象进行修改,那么可以使用浅复制。如果对象包含的引用类型成员是可变的,或者需要对复制后的对象进行修改,那么应该使用深复制。

代码演示

    

原型模式是一种创建型设计模式,它使用原型实例来创建对象的克隆。这种模式通过复制现有对象的原型来创建新的对象,而不是通过实例化类来创建。在Java中,可以通过实现Cloneable接口和重写clone()方法来实现原型模式。

// 创建一个实现Cloneable接口的原型类
class Rectangle implements Cloneable {
    private int width;
    private int height;
  
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
  
    // 重写clone()方法
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
  
    public int getWidth() {
        return width;
    }
  
    public int getHeight() {
        return height;
    }
  
    public void setWidth(int width) {
        this.width = width;
    }
  
    public void setHeight(int height) {
        this.height = height;
    }
}

// 客户端代码
public class PrototypeDemo {
    public static void main(String[] args) {
        // 创建原型对象
        Rectangle rectangle = new Rectangle(10, 20);
  
        try {
            // 克隆原型对象
            Rectangle clonedRectangle = (Rectangle) rectangle.clone();
  
            // 修改克隆对象的属性
            clonedRectangle.setWidth(30);
            clonedRectangle.setHeight(40);
  
            // 输出原型对象和克隆对象的属性
            System.out.println("原型对象的宽度和高度:" + rectangle.getWidth() + ", " + rectangle.getHeight());
            System.out.println("克隆对象的宽度和高度:" + clonedRectangle.getWidth() + ", " + clonedRectangle.getHeight());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

运行以上代码,输出的结果为:

原型对象的宽度和高度:10, 20
克隆对象的宽度和高度:30, 40

以上代码中,Rectangle类实现了Cloneable接口并重写了clone()方法,使得该类的对象可以进行克隆。在客户端代码中,首先创建了一个原型对象rectangle,然后通过调用clone()方法创建了一个克隆对象clonedRectangle。通过修改克隆对象的属性,可以看到原型对象和克隆对象的属性是相互独立的,修改一个对象不会影响另一个对象。

注意:在实际应用中,原型模式还可以结合工厂模式使用,通过工厂类来创建原型对象和克隆对象。这样做的好处是可以隐藏具体的原型类,客户端只需要与工厂类进行交互,而不需要直接与原型类进行交互。

总结

     

原型模式是一种创建型设计模式,它允许通过克隆已有对象来创建新对象,而不需要通过实例化类来创建对象。原型模式的核心思想是使用已有对象作为蓝本,通过克隆来创建新对象,从而避免了重复的对象创建过程。

原型模式的主要优点包括:

  1. 简化对象的创建过程,避免重复的初始化操作;
  2. 提高对象创建的性能;
  3. 可以动态添加或删除原型。

原型模式的主要缺点包括:

  1. 在实现原型模式时,需要实现Cloneable接口,这会引入一定的复杂性;
  2. 对于含有循环引用或包含引用其他不可序列化对象的对象,无法通过原型模式来复制。

在实际应用中,原型模式可用于以下场景:

  1. 对象创建的过程比较复杂,但是对象的创建方式又具有一定的规律;
  2. 需要避免重复对象创建的场景;
  3. 需要动态添加或删除原型的场景。

相关推荐

  1. 设计模式原型模式

    2024-06-10 09:12:01       63 阅读
  2. 设计模式——原型模式

    2024-06-10 09:12:01       49 阅读
  3. 设计模式-原型模式

    2024-06-10 09:12:01       58 阅读
  4. 设计模式-原型模式

    2024-06-10 09:12:01       50 阅读
  5. 设计模式-原型模式

    2024-06-10 09:12:01       46 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-10 09:12:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-10 09:12:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-10 09:12:01       82 阅读
  4. Python语言-面向对象

    2024-06-10 09:12:01       91 阅读

热门阅读

  1. (20)DAC接口--->(005)FPGA实现AD5601接口(五)

    2024-06-10 09:12:01       30 阅读
  2. Set up a WordPress blog with Nginx

    2024-06-10 09:12:01       29 阅读
  3. 为什么选择Python作为AI开发语言

    2024-06-10 09:12:01       29 阅读
  4. 数字化那点事:一文读懂智慧城市

    2024-06-10 09:12:01       32 阅读
  5. unity中常见的角色控制方法

    2024-06-10 09:12:01       36 阅读
  6. 在 .NET Core 中构建工作服务和调度运行

    2024-06-10 09:12:01       33 阅读
  7. (051)FPGA时钟--->(001)时钟介绍

    2024-06-10 09:12:01       32 阅读
  8. 【运维】如何在Ubuntu 22上使用Python 3.8的虚拟环境

    2024-06-10 09:12:01       35 阅读
  9. 在 React 应用中怎么使用useImperativeHandle?

    2024-06-10 09:12:01       20 阅读
  10. 【280个shell脚本】----提示运维工作效率

    2024-06-10 09:12:01       30 阅读
  11. 探索PostgreSQL的多模型世界:灵活存储,无限可能

    2024-06-10 09:12:01       33 阅读