5. 原型模式

原型模式

在软件设计中,我们经常需要频繁创建大量结构相同、内容类似的对象,传统方式往往通过 `new` 的方式反复构造。但是对于某些对象来说,**构建成本高、配置复杂、甚至依赖外部资源**。

这时,一个非常优雅的解决方案就是 **原型模式(Prototype Pattern)**。

一、什么是原型模式?

**原型模式(Prototype Pattern)**:

> 使用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。

也就是说,不再用 `new Xxxx()`,而是 **通过克隆(clone)直接复制已有对象**。

官方话术听起来很抽象?

一句话总结就是:

> **原型模式就是用"复制"代替"重新创建"。**


二、为什么需要原型模式?

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

1. 对象创建成本高

例如:

* 复杂对象构造

* 大量字段初始化

* IO 读取配置后生成对象

使用 clone 可以避免重复初始化。


2. 需要大量相似对象

比如:

* 游戏中大量相似的怪物对象

* 工厂中创建大量模板对象

* 配置对象复制并局部修改


3. 需要在运行时动态决定对象类型

不通过 if-else / new 语句

而通过原型列表(原型注册表)创建。


三、原型模式结构(UML 类图)

```

┌─────────────────────┐

│ Prototype 原型接口 │<────────┐

└─────────────────────┘ │ clone()

▲ │

│ │

┌───────────────────────┐ │

│ ConcretePrototype 具体原型类 │

└───────────────────────┘

│ clone()

┌──────────────────────┐

│ Client 客户端 │

└──────────────────────┘

```


四、Java 实现原型模式(浅拷贝版本)

下面用你的例子:**飞机 Plane 克隆**。

1. 原型接口

```java

public interface PlanePrototype extends Cloneable {

PlanePrototype clonePlanePrototype();

}

```


2. 具体原型类

```java

public class Plane implements PlanePrototype {

private String planeName;

private String planeId;

public Plane(String planeName, String planeId) {

this.planeName = planeName;

this.planeId = planeId;

}

@Override

public PlanePrototype clonePlanePrototype() {

try {

return (Plane) super.clone(); // 浅拷贝

} catch (CloneNotSupportedException e) {

throw new RuntimeException(e);

}

}

@Override

public String toString() {

return planeName + " - " + planeId;

}

}

```


3. 客户端调用

```java

public class ClientDemo {

public static void main(String[] args) {

Plane plane = new Plane("飞机1", "001");

Plane copy = (Plane) plane.clonePlanePrototype();

System.out.println(plane);

System.out.println(copy);

}

}

```

输出结果两个对象内容一样,但它们是 **不同的对象实例**。


五、浅拷贝 vs 深拷贝

浅拷贝:复制对象,但共享引用字段

如果对象内部有引用类型:

```java

class Plane {

Engine engine;

}

```

浅拷贝会导致:

```

plane.engine == copy.engine (true)

```

两个对象共享同一个 engine → 有风险。


深拷贝:复制对象 + 复制内部引用对象

深拷贝实现方式:

```java

@Override

public PlanePrototype clonePlanePrototype() {

try {

Plane plane = (Plane) super.clone();

plane.engine = this.engine.clone(); // 深拷贝引用对象

return plane;

} catch (Exception e) {

throw new RuntimeException(e);

}

}

```

适合复杂对象复制。


六、原型注册表(Prototype Manager)

当系统需要**按类型创建对象**时,可以把原型对象放到 Map 中:

```java

Map<String, PlanePrototype> registry = new HashMap<>();

registry.put("fighter", new Plane("战斗机", "F-001"));

registry.put("civil", new Plane("客机", "C-001"));

// 根据 key 复制原型

Plane clone = (Plane) registry.get("fighter").clonePlanePrototype();

```

→ 运行时动态决定"类"是什么,不需要写 new。

这是原型模式的进阶用法。


七、原型模式的优点

**提高对象创建性能**(避免重复构造)

**避免重复初始化**

**运行时动态生成对象**

**简化代码,只需 clone 就能创建大量对象**


八、原型模式的缺点

深拷贝复杂

clone() 容易滥用

Java 的 Cloneable 接口设计较老旧(不是最优雅)

如果对象内部结构复杂,深拷贝维护成本较高。


九、实际开发中何时使用原型模式?

推荐场景:

需要频繁创建结构类似的对象

创建成本高的对象(复杂构造、运行依赖)

配置类模板复制

游戏开发、图形系统等需要大量相似对象的场景

不推荐场景:

对象结构非常复杂

有大量需要深拷贝的对象

clone() 使用会降低代码可读性


十、总结

原型模式是一种简单却非常实用的设计模式,本质是:

> **用已有对象当作模板,通过克隆来创建新对象。**

优点是提升性能、减少 new 复杂对象的开销;缺点是深拷贝难维护。

对于 Java 开发来说,掌握浅拷贝 + 深拷贝 + Prototype 注册表,就已经足够应对绝大多数项目场景。

相关推荐
Amumu121382 天前
Js: 构造函数、继承、面向对象
原型模式
砍光二叉树3 天前
【设计模式】创建型-原型模式
设计模式·原型模式
RFCEO4 天前
JavaScript基础课程十四、原型与原型链(JS 核心底层)
开发语言·原型模式·prototype原型详解·javascript基础课·构造函数原型方法定义与使用·js原型链继承机制入门·t原型链顶层null原理
new code Boy5 天前
前端核心基础汇总
开发语言·javascript·原型模式
爱写bug的野原新之助5 天前
爬虫之补环境脚本:脱环境
javascript·爬虫·原型模式
承缘丶7 天前
使用http调用Kettle资源库中的ETL任务
原型模式
夕珩10 天前
单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式、解释器模式、命令模式
单例模式·解释器模式·建造者模式·工厂方法模式·抽象工厂模式·命令模式·原型模式
TON_G-T12 天前
JavaScript 原型与原型链
开发语言·javascript·原型模式
蜜獾云12 天前
设计模式之原型模式:以自己为原型,自己实现自己的对象拷贝逻辑
java·设计模式·原型模式
geovindu12 天前
python: Prototype Pattern
python·设计模式·原型模式