【Java】23种设计模式——5.原型模式

概念

原型模式: 用原型实例创建对象的种类,并通过拷贝这些原型创建新的对象(复制)。

复制有两种,浅拷贝深拷贝

浅拷贝

①对于类中基本数据类型,会直接复制值给拷贝对象;

②对于引用类型(对象类型),只会复制对象的地址,而实际上指向的还是原来的那个对象。

深拷贝

无论是基本类型还是引用类型,深拷贝会将引用类型的所有内容,全部拷贝为一个新的对象,包括对象内部的所有成员变量,也会进行拷贝。

而原型模式,实现的就是深拷贝。

应用场景

  • 对象包含大量的可配置属性,且需要快速生成相似对象(如游戏中的NPC角色)
  • 需要避免重复执行的耗时的初始化操作(如数据库连接、文件读取)
  • 系统需要隔离对象的创建和使用逻辑(结合工厂模式动态生成对象)

使用

假设有Student对象。

/**
 * 原型类: 学生
 * @Author:lyj
 * @Date:2025/5/5 15:59
 */
@Data
public class Student {
    private int id;         // id
    private int age;        // 年龄
    private int grade;      // 年级
    private String name;    // 姓名
    private String college; // 大学
    private String profession;  // 专业
    private List<String> awards;    // 奖励

    /**
     * 构造方法
     * @param id id
     * @param age 年龄
     * @param grade 年级
     * @param name 姓名
     * @param college 大学
     * @param profession 专业
     * @param awards 奖励
     */
    public Student(int id , int age , int grade , String name , String college , String profession , List<String> awards){
        this.id = id;
        this.age = age;
        this.grade = grade;
        this.name = name;
        this.college = college;
        this.profession = profession;
        this.awards = awards;
    }
}

如果我们想要用原型模式,对它进行浅拷贝,可以实现``Cloneable 接口。

@Data
public class Student implements Cloneable {
	// ……

    /**
     * 重写clone方法(浅拷贝)
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    public Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
}

深拷贝方法如下:

/**
 * 重写clone方法(深拷贝)
 * @return
 */
@Override
public Student clone()  {
	try {
		Student student = (Student) super.clone();
		// 手动复制引用类型字段
		student.awards = (List<String>) this.awards;
		return student;
	}catch (CloneNotSupportedException e){
		throw new AssertionError();
	}
}

测试拷贝:

// 原始独享
List<String> awards = List.of("数学","语文","英语");
Student student = new Student(1, 18, 3, "张三", "计算机科学与技术学院", "计算机科学与技术", awards);
// 克隆对象
Student clone = student.clone();
// 修改克隆对象的引用子弹(不影响原字段)
clone.setAwards(List.of("物理","化学","生物"));
System.out.println("原对象:" +student);    // 原对象:Student(id=1, age=18, grade=3, name=张三, college=计算机科学与技术学院, profession=计算机科学与技术, awards=[数学, 语文, 英语])
System.out.println("克隆对象:" +clone);     // 克隆对象:Student(id=1, age=18, grade=3, name=张三, college=计算机科学与技术学院, profession=计算机科学与技术, awards=[物理, 化学, 生物])
posted @ 2025-06-20 15:20  陆陆无为而治者  阅读(22)  评论(0)    收藏  举报