【设计模式-原型】

devtools/2024/10/24 22:56:19/

**原型模式(Prototype Pattern)**是一种创建型设计模式,旨在通过复制现有对象的方式来创建新对象,而不是通过实例化类来创建对象。该模式允许对象通过克隆(复制)来创建新的实例,因此避免了重新创建对象带来的开销,尤其在对象创建复杂、耗时的情况下。

1. 定义

原型模式使用一个现有的对象作为原型,创建新对象时,通过克隆该对象来生成新对象。这个模式提供了一个接口来复制已有对象,并允许客户端通过该接口请求复制对象。

2. 原型模式的结构

原型模式主要包含以下几个部分:

  • Prototype(原型接口):定义了一个 clone() 方法,用于克隆自身。具体实现可以是浅拷贝或深拷贝。
  • ConcretePrototype(具体原型类):实现了 Prototype 接口,并实现 clone() 方法。通常使用 Java 的 Cloneable 接口来实现克隆。
  • Client(客户端):通过调用原型的 clone() 方法来获取对象,而不是直接通过构造函数创建对象。

3. 原型模式的工作原理

原型模式的关键在于提供一个能够复制自身的原型接口,并在具体类中实现该接口的 clone() 方法。通过克隆现有对象来创建新对象,这样既节省了资源,又能提高系统性能。

3.1 浅拷贝 vs 深拷贝
  • 浅拷贝:复制对象时,拷贝所有字段,但如果字段是对象类型,则只复制对象的引用。换句话说,浅拷贝只是复制了对象的内存地址,因此新旧对象共享相同的引用类型字段。
  • 深拷贝:不仅复制字段,还会递归地复制引用类型的对象,确保新对象是独立的,彼此不共享任何状态。

4. 原型模式的 UML 类图

在这里插入图片描述

5. Java 中的原型模式示例

Java 提供了 Cloneable 接口和 Object 类中的 clone() 方法,支持原型模式的实现。

5.1 示例代码
class Prototype implements Cloneable {private String name;private int age;public Prototype(String name, int age) {this.name = name;this.age = age;}// 实现 clone 方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 浅拷贝}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Prototype{name='" + name + "', age=" + age + "}";}
}public class PrototypePatternDemo {public static void main(String[] args) {try {// 创建原型对象Prototype original = new Prototype("Alice", 25);System.out.println("Original Object: " + original);// 克隆原型对象Prototype clone = (Prototype) original.clone();System.out.println("Cloned Object: " + clone);// 修改原始对象,会影响克隆对象System.out.println("Objects are different: " + (original != clone));} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

输出:

Original Object: Prototype{name='Alice', age=25}
Cloned Object: Prototype{name='Alice', age=25}
Objects are different: true
5.2 深拷贝示例
class Address implements Cloneable {private String city;private String country;public Address(String city, String country) {this.city = city;this.country = country;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 浅拷贝}@Overridepublic String toString() {return "Address{city='" + city + "', country='" + country + "'}";}
}class Person implements Cloneable {private String name;private int age;private Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {// 深拷贝: 克隆引用类型字段Person cloned = (Person) super.clone();cloned.address = (Address) address.clone();  // 深拷贝 Address 对象return cloned;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";}
}public class DeepCopyDemo {public static void main(String[] args) {try {// 创建原型对象Address address = new Address("New York", "USA");Person person1 = new Person("John", 30, address);System.out.println("Original: " + person1);// 克隆对象Person person2 = (Person) person1.clone();System.out.println("Cloned: " + person2);// 修改原始对象中的地址,不影响克隆对象中的地址address.city = "Los Angeles";System.out.println("After modifying address:");System.out.println("Original: " + person1);System.out.println("Cloned: " + person2);} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

输出:

Original: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
After modifying address:
Original: Person{name='John', age=30, address=Address{city='Los Angeles', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}

6. 原型模式的优点

  • 性能优化:当创建对象代价较高时,克隆可以比通过构造函数创建新对象更加高效。
  • 动态创建对象原型模式允许在运行时动态地创建对象,而不需要知道具体的类或实现。
  • 减少子类数目:避免了频繁的使用子类去生成对象,通过克隆可以生成对象的不同版本。

7. 原型模式的缺点

  • 深拷贝复杂:如果对象中有复杂的嵌套对象或循环引用,深拷贝的实现会非常复杂,需要逐层克隆每个引用的对象。
  • 依赖于具体的实现:克隆对象需要依赖类的 clone() 方法,可能会限制类的灵活性。

8. 原型模式的应用场景

  • 资源消耗大的对象创建:比如对象创建需要读取数据库、大量计算或需要访问网络资源时,可以使用原型模式进行克隆操作。
  • 重复创建相似对象:在某些系统中,需要频繁创建内容相似的对象,使用原型模式可以节省时间。
  • 不可变对象的场景:某些情况下,创建后不可修改的对象,原型模式可以保证对象的唯一性和一致性。

9. 总结

原型模式是一种有效的设计模式,适用于创建开销较大的对象。通过 clone() 方法,可以快速创建相同或类似的对象,减少创建新对象的成本。同时,它支持浅拷贝和深拷贝的灵活实现,在复杂的对象克隆场景下,深拷贝需要特别的设计。


http://www.ppmy.cn/devtools/128530.html

相关文章

【Linux】平台设备驱动

在设备驱动模型中,引入总线的概念可以对驱动代码和设备信息进行分离。但是驱动中总线的概念是软件层面的一种抽象,与我们SOC中物理总线的概念并不严格相等。 物理总线:芯片与各个功能外设之间传送信息的公共通信干线,其中又包括数…

云原生-降本增效最佳案例分享-学习笔记

云原生(以技术为“内核”,一个核心的位置)产业发展态势分析,云原生(运维和研发测)国内发展迅猛2021年市场的规模已经达到了千亿元,企业对云原生的投入和支出!不同行业对于云原生的重…

java第三天(游戏开发)

学到 双缓存机制 public void paint(Graphics g) {// super.paint(g);//createImage(width, height) 是一个方法调用,它创建了一个指定宽度和高度的空图像缓冲区。这个方//法可以在 Component 类中找到,因此任何从 Component 继承的类(比…

深度学习的程序实例

以下是一个使用深度学习的程序实例: import tensorflow as tf from tensorflow.keras.datasets import mnist from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.optimizers import RMSp…

二、Linux 入门教程:开启大数据领域的神奇之旅

Linux 入门教程:开启大数据领域的神奇之旅 在当今这个飞速发展的数字化时代,大数据所具有的重要性正日益凸显出来。而 Linux 作为一种极为强大的操作系统,在大数据这一广阔的领域当中发挥着至关重要、不可或缺的关键作用。倘若你怀有涉足大数…

背包九讲——完全背包问题

目录 完全背包问题 问题定义 动态规划解法 状态转移方程 初始化 遍历顺序 三种解法: 朴素版——枚举k 进阶版——dp正推(一维滚动数组) 背包问题第三讲——完全背包问题 背包问题是一类经典的组合优化问题,通常涉及在限定…

线程同步之双摄

如何实现两个摄像头进行同步,并利用同步的信号做一些事情, 比如stereo camera 做深度,如果是自己整的两个camera,同步就需要自己做, 那么这时候可以利用线程同步手写一个,下面给一个示例代码: …

Java 代码优化 修饰器模式(Decorator Pattern)

在软件设计中,装饰模式是一种非常有用的结构型设计模式,它允许你在不修改现有类的情况下,动态地为对象添加新的功能。这个模式通过将对象包裹在装饰器对象中,实现功能的扩展和增强。 装饰模式的核心思想 核心问题:有时…