当前位置: 首页 > news >正文

原型模式详细介绍和代码实现

🎯 设计模式专栏,持续更新中, 欢迎订阅:JAVA实现设计模式
🛠️ 希望小伙伴们一键三连,有问题私信都会回复,或者在评论区直接发言

Java实现原型模式

介绍: 原型模式(Prototype Pattern)是一种创建型设计模式,允许通过复制已有对象来创建新对象,而不需要依赖其具体类。这种模式的关键在于克隆现有对象,而不是通过直接实例化新对象,从而避免重复的复杂对象构建过程。

🎯 案例场景:

假设我们在开发一个游戏角色系统,每个角色都有不同的属性,比如力量、敏捷和智力。创建一个新角色需要耗费大量的计算资源(如生成外貌、装备等)。如果我们想要快速创建一个与现有角色相似的新角色,只需要在原有角色基础上进行微调,而不重新生成所有属性。

我们可以使用原型模式,通过复制已有角色对象,再对其进行调整,来生成新的角色。

原型模式的核心步骤:

  1. Prototype 接口:定义 clone() 方法,所有需要被复制的对象实现该接口。
  2. 具体原型类:实现 clone() 方法,用于创建对象的副本。
  3. 客户端代码:通过调用 clone() 方法来复制已有对象。

🧑‍💻 Java代码实现:

在这里插入图片描述

import java.util.HashMap;
import java.util.Map;// 1. 定义原型接口 Prototype
interface GameCharacter extends Cloneable {GameCharacter clone();void display();
}// 2. 具体的角色类实现原型接口
class Warrior implements GameCharacter {private String name;private int strength;private int agility;private int intelligence;public Warrior(String name, int strength, int agility, int intelligence) {this.name = name;this.strength = strength;this.agility = agility;this.intelligence = intelligence;}// 实现 clone 方法@Overridepublic Warrior clone() {try {return (Warrior) super.clone();  // 调用 Object 类的 clone 方法} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}// 展示角色信息@Overridepublic void display() {System.out.println("Warrior [Name: " + name + ", Strength: " + strength +", Agility: " + agility + ", Intelligence: " + intelligence + "]");}
}// 3. 客户端代码,使用原型模式
public class PrototypePatternDemo {public static void main(String[] args) {// 创建一个原始的角色Warrior originalWarrior = new Warrior("Arthas", 80, 50, 30);originalWarrior.display();// 使用克隆方法复制角色Warrior clonedWarrior = originalWarrior.clone();// 修改克隆对象的某些属性clonedWarrior.display();// 现在,原始角色和克隆角色的内存地址不同,但属性相同System.out.println("Original Warrior HashCode: " + originalWarrior.hashCode());System.out.println("Cloned Warrior HashCode: " + clonedWarrior.hashCode());}
}

📋 解释:

  1. GameCharacter 接口:定义了 clone() 方法,表示所有实现这个接口的类都可以被克隆。
  2. Warrior:实现了 GameCharacter 接口,并通过 super.clone() 进行浅克隆。这个方法通过复制对象的当前状态来创建一个新实例。
  3. 客户端代码:首先创建了一个 Warrior 对象 originalWarrior,并使用其 clone() 方法创建了一个副本 clonedWarrior。然后可以自由修改克隆对象的属性,而不影响原始对象。

🌟 应用场景:

  1. 对象创建开销大,不希望每次都通过构造函数创建。
  2. 需要保存对象的初始状态,以便在不同地方进行修改和操作。
  3. 游戏开发中,需要频繁创建相似但稍有不同的角色或物品。

深拷贝和浅拷贝

浅拷贝:复制对象时,只复制对象的基本属性引用类型的引用。即如果对象的属性是引用类型(如数组、对象),浅拷贝只会复制这些引用,而不是引用所指向的实际对象。因此,拷贝后的对象和原始对象共享这些引用类型的数据,修改引用类型的内容会影响原始对象。

深拷贝:不仅会复制对象的基本属性,还会递归地复制引用类型所指向的对象,即引用对象也会完全复制成一个新的副本。这样,拷贝后的对象与原始对象完全独立,修改拷贝对象的引用类型内容,不会影响原始对象。

🌟 案例解释:

假设我们有一个 Person 类,里面包含基本类型属性 name 和引用类型 address

1. 浅拷贝示例:

浅拷贝只复制基本属性和引用对象的引用,不复制引用对象本身。

class Address {String city;public Address(String city) {this.city = city;}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}// 浅拷贝@Overridepublic Person clone() {try {return (Person) super.clone();  // 调用 Object 的 clone 方法} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}public void display() {System.out.println("Name: " + name + ", City: " + address.city);}
}public class ShallowCopyDemo {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("John", address);Person person2 = person1.clone();  // 浅拷贝// 显示原始和克隆对象person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: New York// 修改克隆对象的 addressperson2.address.city = "San Francisco";// 浅拷贝后,原始对象的 address 也被改变person1.display();  // Name: John, City: San Franciscoperson2.display();  // Name: John, City: San Francisco}
}

结果解释

  • person2person1 的浅拷贝。
  • person2address.city 修改为 "San Francisco" 后,person1address.city 也变成了 "San Francisco"。这是因为浅拷贝只复制了引用,两个对象共享同一个 Address 对象。
2. 深拷贝示例:

深拷贝需要复制所有对象,包括引用对象中的数据。

class Address implements Cloneable {String city;public Address(String city) {this.city = city;}@Overridepublic Address clone() {try {return (Address) super.clone();  // 克隆 Address 对象} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}// 深拷贝@Overridepublic Person clone() {try {Person clonedPerson = (Person) super.clone();clonedPerson.address = address.clone();  // 深拷贝 Addressreturn clonedPerson;} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}public void display() {System.out.println("Name: " + name + ", City: " + address.city);}
}public class DeepCopyDemo {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("John", address);Person person2 = person1.clone();  // 深拷贝// 显示原始和克隆对象person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: New York// 修改克隆对象的 addressperson2.address.city = "San Francisco";// 深拷贝后,原始对象的 address 未被改变person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: San Francisco}
}

结果解释

  • person2person1 的深拷贝。
  • person2address.city 修改为 "San Francisco" 后,person1address.city 仍然是 "New York"。这是因为深拷贝创建了 Address 对象的独立副本,两个对象不再共享同一个引用。

🔍 关键区别总结:

  1. 浅拷贝
    • 只复制对象的基本类型属性引用的地址,不复制引用的实际内容。
    • 拷贝后的对象与原对象共享引用类型的对象。
    • 如果修改了引用类型的数据,原始对象也会受到影响。
  2. 深拷贝
    • 复制对象的所有属性,包括递归复制引用类型对象
    • 拷贝后的对象和原始对象完全独立,互不影响。
    • 修改其中一个对象的引用类型内容,不会影响另一个对象。
http://www.lryc.cn/news/440742.html

相关文章:

  • ArcGIS Pro SDK (十三)地图创作 5 图层样式
  • 【Python报错已解决】 Requests.exceptions.ProxyError: HTTPSConnectionPool
  • 现在量化中普遍使用QMT和PTrade?哪家可以同时提供QMT/PTrade?
  • 【计算机网络】UDP 协议详解及其网络编程应用
  • 基于ESP32S3的链接大语言模型对话模块
  • Cpp输出多字符常量警告
  • Maven从入门到精通(二)
  • 【Kubernetes】常见面试题汇总(二十四)
  • 最低成本的游戏串流方案分享 如何自己打造云电脑?
  • python运行时错误:找不到fbgemm.dll
  • 给虚拟机linux系统安装交叉编译工具链
  • Redhat 7,8系(复刻系列) 一键部署Oracle21c-xe rpm
  • Web植物管理系统-下位机部分
  • leetcode169. 多数元素
  • 从大脑图谱/ROI中提取BOLD信号
  • Java-数据结构-优先级队列(堆)-(一) (;´д`)ゞ
  • 工厂模式(二):工厂方法模式
  • 【洛谷】P11036 【MX-X3-T3】「RiOI-4」GCD 与 LCM 问题 的题解
  • MyBatis系统学习(三)——动态SQL
  • get_property --Cmakelist之中
  • 【Redis】Redis 典型应用 - 分布式锁原理与实现
  • Pybind11的使用
  • 鸿蒙-沉浸式pc端失效
  • 【资料分析】刷题日记1
  • nodejs+express+vue教辅课程辅助教学系统 43x2u前后端分离项目
  • 96-javahashmap底层原理
  • AI逻辑推理入门
  • 力扣3014.输入单词需要的最少按键次数I
  • 【Git】远程仓库
  • 苹果手机铃声怎么设置自己的歌?3个方法自定义手机铃声