设计模式——原型模式

原型模式 (Prototype Pattern)

什么是原型模式?

原型模式是一种创建型设计模式,它允许你通过复制现有对象来创建新对象,而不是通过实例化类来创建。

简单来说:原型模式就是通过克隆(复制)现有对象来创建新对象。

生活中的例子

想象一下:

  • 复印文档:复印一份已有的文档,而不是重新写一份
  • 克隆生物:克隆一只羊,而不是重新培育一只
  • 复制粘贴:复制一段文字,而不是重新输入

为什么需要原型模式?

传统方式的问题

java 复制代码
// 创建对象
User user1 = new User("张三", 25);
User user2 = new User("张三", 25);  // 需要重新设置属性

问题

  1. 重复代码:需要重复设置相同的属性
  2. 创建复杂:如果对象创建过程复杂,需要重复执行
  3. 性能开销:如果对象创建耗时,会影响性能

原型模式的优势

java 复制代码
// 克隆对象
User user1 = new User("张三", 25);
User user2 = user1.clone();  // 直接克隆,无需重新设置属性

优势

  1. 简化创建:通过克隆简化对象的创建
  2. 提高性能:避免重复执行复杂的创建过程
  3. 动态创建:可以在运行时动态创建对象

原型模式的结构

复制代码
┌─────────────────────┐
│    Prototype        │  原型接口
├─────────────────────┤
│ + clone(): Object   │
└──────────┬──────────┘
           │ 实现
           ├──┬──────────────────┬──────────────┐
           │                    │              │
┌──────────┴──────┐  ┌───────────┴───────┐  ┌───┴────────┐
│ ConcreteProto1   │  │ ConcreteProto2    │  │ ...       │  具体原型
├─────────────────┤  ├───────────────────┤  ├────────────┤
│ + clone(): Obj   │  │ + clone(): Obj    │  │            │
└─────────────────┘  └───────────────────┘  └────────────┘

代码示例

1. 定义原型接口

java 复制代码
/**
 * 原型接口
 */
public interface Prototype {
    /**
     * 克隆方法
     */
    Prototype clone();
}

2. 定义地址类(引用类型)

java 复制代码
/**
 * 地址类(引用类型,用于演示浅拷贝和深拷贝)
 */
public class Address implements Cloneable {
    private String city;
    private String district;
    
    public Address(String city, String district) {
        this.city = city;
        this.district = district;
    }
    
    // Getter和Setter方法
    public String getCity() {
        return city;
    }
    
    public void setCity(String city) {
        this.city = city;
    }
    
    public String getDistrict() {
        return district;
    }
    
    public void setDistrict(String district) {
        this.district = district;
    }
    
    @Override
    public String toString() {
        return city + "市" + district;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

3. 实现具体原型

java 复制代码
/**
 * 用户类(实现原型接口和Cloneable接口)
 */
public class User implements Prototype, Cloneable {
    private String name;
    private int age;
    private Address address;
    
    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    
    /**
     * 浅拷贝
     */
    @Override
    public User clone() {
        try {
            return (User) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }
    
    /**
     * 深拷贝
     */
    public User deepClone() {
        try {
            User user = (User) super.clone();
            user.address = (Address) address.clone();
            return user;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }
    
    // Getter和Setter方法
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public Address getAddress() {
        return address;
    }
    
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + ", address=" + address + "}";
    }
}

4. 使用原型

java 复制代码
/**
 * 原型模式测试类
 * 演示浅拷贝和深拷贝的区别
 */
public class PrototypeTest {
    
    public static void main(String[] args) {
        System.out.println("=== 原型模式测试 ===\n");
        
        // 创建原始对象
        Address address = new Address("北京", "朝阳区");
        User originalUser = new User("张三", 25, address);
        System.out.println("原始用户: " + originalUser);
        
        System.out.println("\n--- 浅拷贝 ---");
        User shallowCopy = originalUser.clone();
        System.out.println("浅拷贝用户: " + shallowCopy);
        System.out.println("原始用户 == 浅拷贝用户: " + (originalUser == shallowCopy));
        System.out.println("原始地址 == 浅拷贝地址: " + (originalUser.getAddress() == shallowCopy.getAddress()));
        
        // 修改浅拷贝的地址
        shallowCopy.getAddress().setCity("上海");
        System.out.println("\n修改浅拷贝的地址后:");
        System.out.println("原始用户: " + originalUser);
        System.out.println("浅拷贝用户: " + shallowCopy);
        System.out.println("注意:原始用户的地址也被修改了(浅拷贝问题)");
        
        System.out.println("\n--- 深拷贝 ---");
        User deepCopy = originalUser.deepClone();
        System.out.println("深拷贝用户: " + deepCopy);
        System.out.println("原始用户 == 深拷贝用户: " + (originalUser == deepCopy));
        System.out.println("原始地址 == 深拷贝地址: " + (originalUser.getAddress() == deepCopy.getAddress()));
        
        // 修改深拷贝的地址
        deepCopy.getAddress().setCity("广州");
        System.out.println("\n修改深拷贝的地址后:");
        System.out.println("原始用户: " + originalUser);
        System.out.println("深拷贝用户: " + deepCopy);
        System.out.println("注意:原始用户的地址没有被修改(深拷贝正确)");
        
        System.out.println("\n=== 原型模式的优势 ===");
        System.out.println("1. 简化创建:通过克隆简化对象的创建");
        System.out.println("2. 提高性能:避免重复执行复杂的创建过程");
        System.out.println("3. 动态创建:可以在运行时动态创建对象");
        System.out.println("4. 隐藏细节:隐藏对象创建的细节");
    }
}

浅拷贝 vs 深拷贝

浅拷贝

只复制基本类型和对象的引用,不复制引用对象本身。

java 复制代码
public class Address implements Cloneable {
    private String city;
    
    // ...
}

public class User implements Cloneable {
    private String name;
    private Address address;  // 引用类型
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝,只复制address的引用
    }
}

问题:修改克隆对象的address会影响原对象。

深拷贝

复制所有对象,包括引用对象。

java 复制代码
public class User implements Cloneable {
    private String name;
    private Address address;
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.address = (Address) address.clone();  // 深拷贝
        return user;
    }
}

原型模式的优点

  1. 简化创建:通过克隆简化对象的创建
  2. 提高性能:避免重复执行复杂的创建过程
  3. 动态创建:可以在运行时动态创建对象
  4. 隐藏细节:隐藏对象创建的细节

原型模式的缺点

  1. 深拷贝复杂:实现深拷贝可能比较复杂
  2. 类依赖:类必须实现Cloneable接口
  3. 循环引用:处理循环引用比较困难

适用场景

  1. 对象创建复杂:对象的创建过程复杂或耗时
  2. 对象相似:需要创建多个相似的对象
  3. 保护性拷贝:需要保护原对象不被修改
  4. 动态创建:需要在运行时动态创建对象

常见应用场景

  • 对象池:对象池中的对象克隆
  • 文档编辑:复制粘贴文档内容
  • 游戏开发:克隆游戏角色或道具
  • 配置管理:复制配置对象

使用建议

  • 对象创建复杂:使用原型模式
  • 需要多个相似对象:使用原型模式
  • 简单对象:直接使用构造函数即可

注意事项

⚠️ 原型模式虽然有用,但要注意:

  • 区分浅拷贝和深拷贝
  • 处理循环引用
  • 考虑使用序列化实现深拷贝
相关推荐
进击的小头2 小时前
为什么C语言也需要设计模式
c语言·开发语言·设计模式
小码过河.4 小时前
设计模式——外观模式
设计模式·外观模式
ipod7415 小时前
#设计模式
设计模式
小码过河.5 小时前
设计模式——命令模式
设计模式·命令模式
小码过河.6 小时前
设计模式——备忘录模式
设计模式·备忘录模式
代码or搬砖6 小时前
设计模式之单例模式
单例模式·设计模式
一条闲鱼_mytube6 小时前
智能体设计模式(四)模型上下文协议-目标设定与监控-异常处理与恢复
microsoft·设计模式
老蒋每日coding6 小时前
AI Agent 设计模式系列(十)——模型上下文协议 (MCP)
人工智能·设计模式
Yu_Lijing6 小时前
基于C++的《Head First设计模式》笔记——迭代器模式
笔记·设计模式