设计模式-原型模式

设计模式-原型模式案例背景假设我们有一个游戏系统 游戏中需要频繁创建 敌人对象 每个敌人对象包含以下属性 名称 name 血量 health 攻击力 attackPower 防御力 defensePower 敌人的初始属性是通过配置文件加载的 创建敌人对象时

大家好,欢迎来到IT知识分享网。

案例背景

假设我们有一个游戏系统,游戏中需要频繁创建 敌人对象。每个敌人对象包含以下属性:

  • 名称(name)
  • 血量(health)
  • 攻击力(attackPower)
  • 防御力(defensePower)

敌人的初始属性是通过配置文件加载的,创建敌人对象时需要从配置文件中读取数据并初始化。

代码实现

敌人类:Enemy

@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Enemy { / * 名称 */ private String name; / * 血量 */ private int health; / * 攻击力 */ private int attackPower; / * 防御力 */ private int defensePower; @Override public String toString() { return "{" + "name='" + name + '\'' + ", health=" + health + ", attackPower=" + attackPower + ", defensePower=" + defensePower + '}'; } } 

数据来源加载类

/ * 从配置信息中加载敌人信息 */ public class EnemyConfig { public static Enemy loadEnemyFromConfig() { // 模拟数据由配置文件 或 数据库加载 return new Enemy("暗黑巨魔", 100, 10, 5); } } 

测试代码

public class EnemyTest { @Test public void getEnemy() { // 第一次获取敌人对象 加载数据 Enemy enemyA = EnemyConfig.loadEnemyFromConfig(); // 第二次获取敌人对象 加载数据 Enemy enemyB = EnemyConfig.loadEnemyFromConfig(); System.out.println("敌军一号: " + enemyA); System.out.println("敌军二号: " + enemyB); } } 

存在的问题

  1. 重复初始化
  2. 每次创建敌人对象时,都需要从配置文件中加载数据并初始化,导致重复的 I/O 操作和初始化逻辑。
  3. 性能问题
  4. 如果配置文件加载过程耗时较长(如读取数据库或远程接口),频繁创建敌人对象会导致性能下降。
  5. 代码冗余
  6. 初始化逻辑分散在多个地方,难以维护和扩展。

原型模式重构

1. 原型模式的主要内容

定义

原型模式是一种 创建型设计模式,它通过复制现有对象来创建新对象,而不是通过调用构造函数。原型模式的核心思想是 克隆

核心角色

  1. 原型接口(Prototype)
  2. 定义克隆方法的接口。
  3. 具体原型(Concrete Prototype)
  4. 实现原型接口,提供克隆方法的具体实现。
  5. 客户端(Client)
  6. 使用原型对象创建新对象。

2. 使用场景

原型模式适用于以下场景:

  1. 对象创建成本高
  2. 当对象的创建过程非常复杂或耗时,且需要频繁创建相似对象时。
  3. 例如:数据库连接、线程池。
  4. 对象状态相似
  5. 当需要创建的对象与现有对象状态相似时。
  6. 例如:游戏中的敌人、文档模板。
  7. 避免构造函数调用
  8. 当希望避免调用构造函数来创建对象时。
  9. 例如:某些构造函数参数复杂或不可控。

3. 使用原型模式进行重构

重构思路

  1. 定义原型接口
  2. 让 Enemy 类实现 Cloneable 接口,支持克隆。
  3. 实现克隆方法
  4. 在 Enemy 类中实现 clone() 方法,复制现有对象的属性。
  5. 使用原型对象
  6. 从配置文件中加载一个原型对象,后续通过克隆原型对象来创建新对象。

重构后的代码

敌人类:Enemy(实现 Cloneable 接口)

@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Enemy implements Cloneable { / * 名称 */ private String name; / * 血量 */ private int health; / * 攻击力 */ private int attackPower; / * 防御力 */ private int defensePower; @Override public Enemy clone() { try { return (Enemy) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("对象拷贝异常: ", e); } } @Override public String toString() { return "{" + "name='" + name + '\'' + ", health=" + health + ", attackPower=" + attackPower + ", defensePower=" + defensePower + '}'; } } 

数据来源加载类

/ * 从配置信息中加载敌人信息 */ public class EnemyConfig { public static Enemy loadEnemyFromConfig() { // 模拟数据由配置文件 或 数据库加载 return new Enemy("暗黑巨魔", 100, 10, 5); } } 

客户端代码

public class EnemyTest { @Test public void getEnemy() { // 第一次获取敌人对象 加载数据 Enemy enemyA = EnemyConfig.loadEnemyFromConfig(); Enemy enemyB = enemyA.clone(); System.out.println("敌军一号: " + enemyA); System.out.println("敌军二号: " + enemyB); } } 

重构后的优势

  1. 减少初始化成本
  2. 只需要从配置文件中加载一次原型对象,后续通过克隆创建新对象,避免了重复的 I/O 操作和初始化逻辑。
  3. 提升性能
  4. 克隆操作比从配置文件加载数据更快,显著提升了性能。
  5. 代码更简洁
  6. 初始化逻辑集中在原型对象中,客户端代码更简洁、更易维护。

4. 开源项目中的应用

长话短说

1、核心思想

  • 克隆代替创建:通过复制现有对象来创建新对象,而不是通过调用构造函数。
  • 减少创建成本:避免重复执行复杂的初始化逻辑。

2、何时可以使用原型模式?

  • 对象的创建成本高(如需要从配置文件或数据库加载数据)。
  • 需要频繁创建相似对象。
  • 希望避免重复的初始化逻辑。

3、使用思路

  1. 定义原型接口
  2. 定义克隆方法的接口。
  3. 例如:Cloneable 接口。
  4. 实现具体原型
  5. 实现原型接口,提供克隆方法的具体实现。
  6. 例如:实现 Cloneable 接口的类。
  7. 客户端使用原型
  8. 使用原型对象创建新对象。
  9. 例如:调用 clone() 方法复制对象。

设计模式是好东西,用对了项目好维护。但别硬套,不然设计过度,浪费成本。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/175195.html

(0)
上一篇 2025-04-02 09:10
下一篇 2025-04-02 09:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信