设计模式之生成实例_Prototype复制模式_通过复制生成实例
前言
Github:https://github.com/HealerJean
一、原型/复制模式
1、模式概述
原型模式 是一种 创建型设计模式,它通过 复制(克隆)现有对象 来创建新对象,而不是通过 new 调用构造函数。
核心思想:“不 new,直接 clone —— 用现成的模板快速生成新实例。”
-
当对象的创建成本较高(如需数据库查询、复杂计算、网络请求等),而对象结构又相对稳定时,使用原型模式可显著提升性能。
-
原型模式常用于缓存预构建对象、游戏开发中的敌人/道具生成、配置模板复制等场景。
原型模式 = 缓存模板 + 克隆复用
- 它不是“创建新东西”,而是“复制一个现成的”,在性能与灵活性之间取得平衡。
2、使用场景
原型模式适用于以下情况:
- 创建对象的过程 代价高昂(时间、资源消耗大);
- 系统需要 动态决定创建哪些对象,且这些对象类型在运行时才确定;
- 对象具有 多层嵌套或复杂初始化逻辑,但结构相对固定;
- 需要 避免重复初始化 相同配置的对象。
典型例子:
- 游戏中大量相同敌人的生成;
- Excel 中“复制单元格格式”;
- Spring 中的
prototype作用域 Bean(部分实现基于克隆思想)。
3、示例程序:图形对象的克隆缓存
1)抽象原型类 Shape
- 使用
protected字段便于子类访问; - 强制转型为
Shape提升类型安全; - 异常转为运行时异常,避免客户端处理 checked exception。
import lombok.Data;
import lombok.ToString;
/**
* 抽象原型类 —— 实现 Cloneable 接口
*/
@Data
@ToString
public abstract class Shape implements Cloneable {
protected String id;
protected String type;
public abstract void draw();
@Override
public Shape clone() {
try {
return (Shape) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone not supported for " + getClass(), e);
}
}
}
2)具体原型类
a、Rectangle
@Data
@ToString(callSuper = true)
public class Rectangle extends Shape {
private String rectangleName; // 修正拼写:pectangleName → rectangleName
public Rectangle() {
this.type = "Rectangle";
}
@Override
public void draw() {
System.out.println(id + ":" + type + ":" + rectangleName);
}
}
b、 Square
@Data
@ToString(callSuper = true)
public class Square extends Shape {
private String squareName;
public Square() {
this.type = "Square";
}
@Override
public void draw() {
System.out.println(id + ":" + type + ":" + squareName);
}
}
3)原型管理器 ShapeCache
import java.util.HashMap;
import java.util.Map;
/**
* 原型管理器 —— 缓存并提供克隆对象
*/
public class ShapeCache {
private static final Map<String, Shape> prototypeMap = new HashMap<>();
/**
* 注册原型
*/
public static void register(Shape prototype) {
prototypeMap.put(prototype.getType(), prototype);
}
/**
* 获取克隆对象(全新实例)
*/
public static Shape get(String type) {
Shape prototype = prototypeMap.get(type);
if (prototype == null) {
throw new IllegalArgumentException("Prototype not found for type: " + type);
}
return prototype.clone();
}
}
4)客户端测试 Main
关键验证:克隆对象是 独立副本,修改它不会影响原型缓存。
public class Main {
public static void main(String[] args) {
// 1. 注册原型
Rectangle rectProto = new Rectangle();
rectProto.setId("1");
rectProto.setRectangleName("DefaultRect");
ShapeCache.register(rectProto);
Square squareProto = new Square();
squareProto.setId("2");
squareProto.setSquareName("DefaultSquare");
ShapeCache.register(squareProto);
// 2. 获取克隆对象(全新实例)
Rectangle rect1 = (Rectangle) ShapeCache.get("Rectangle");
rect1.draw(); // 输出: 1:Rectangle:DefaultRect
Square square1 = (Square) ShapeCache.get("Square");
square1.draw(); // 输出: 2:Square:DefaultSquare
// 3. 修改克隆对象不影响原型
rect1.setId("100");
rect1.setRectangleName("ModifiedRect");
rect1.draw(); // 输出: 100:Rectangle:ModifiedRect
// 原型未变
Rectangle original = (Rectangle) ShapeCache.get("Rectangle");
original.draw(); // 仍输出: 1:Rectangle:DefaultRect
}
}


