**原型模式(Prototype Pattern)**是一种创建型设计模式,旨在通过复制现有对象的方式来创建新对象,而不是通过实例化类来创建对象。该模式允许对象通过克隆(复制)来创建新的实例,因此避免了重新创建对象带来的开销,尤其在对象创建复杂、耗时的情况下。
1. 定义
原型模式使用一个现有的对象作为原型,创建新对象时,通过克隆该对象来生成新对象。这个模式提供了一个接口来复制已有对象,并允许客户端通过该接口请求复制对象。
2. 原型模式的结构
原型模式主要包含以下几个部分:
- Prototype(原型接口):定义了一个 
clone()方法,用于克隆自身。具体实现可以是浅拷贝或深拷贝。 - ConcretePrototype(具体原型类):实现了 
Prototype接口,并实现clone()方法。通常使用 Java 的Cloneable接口来实现克隆。 - Client(客户端):通过调用原型的 
clone()方法来获取对象,而不是直接通过构造函数创建对象。 
3. 原型模式的工作原理
原型模式的关键在于提供一个能够复制自身的原型接口,并在具体类中实现该接口的 clone() 方法。通过克隆现有对象来创建新对象,这样既节省了资源,又能提高系统性能。
3.1 浅拷贝 vs 深拷贝
- 浅拷贝:复制对象时,拷贝所有字段,但如果字段是对象类型,则只复制对象的引用。换句话说,浅拷贝只是复制了对象的内存地址,因此新旧对象共享相同的引用类型字段。
 - 深拷贝:不仅复制字段,还会递归地复制引用类型的对象,确保新对象是独立的,彼此不共享任何状态。
 
4. 原型模式的 UML 类图

5. Java 中的原型模式示例
Java 提供了 Cloneable 接口和 Object 类中的 clone() 方法,支持原型模式的实现。
5.1 示例代码
class Prototype implements Cloneable {
    private String name;
    private int age;
    
    public Prototype(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 实现 clone 方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "Prototype{name='" + name + "', age=" + age + "}";
    }
}
public class PrototypePatternDemo {
    public static void main(String[] args) {
        try {
            // 创建原型对象
            Prototype original = new Prototype("Alice", 25);
            System.out.println("Original Object: " + original);
            // 克隆原型对象
            Prototype clone = (Prototype) original.clone();
            System.out.println("Cloned Object: " + clone);
            // 修改原始对象,会影响克隆对象
            System.out.println("Objects are different: " + (original != clone));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
 
输出:
Original Object: Prototype{name='Alice', age=25}
Cloned Object: Prototype{name='Alice', age=25}
Objects are different: true
 
5.2 深拷贝示例
class Address implements Cloneable {
    private String city;
    private String country;
    public Address(String city, String country) {
        this.city = city;
        this.country = country;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝
    }
    @Override
    public String toString() {
        return "Address{city='" + city + "', country='" + country + "'}";
    }
}
class Person implements Cloneable {
    private String name;
    private int age;
    private Address address;
    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 深拷贝: 克隆引用类型字段
        Person cloned = (Person) super.clone();
        cloned.address = (Address) address.clone();  // 深拷贝 Address 对象
        return cloned;
    }
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
    }
}
public class DeepCopyDemo {
    public static void main(String[] args) {
        try {
            // 创建原型对象
            Address address = new Address("New York", "USA");
            Person person1 = new Person("John", 30, address);
            System.out.println("Original: " + person1);
            // 克隆对象
            Person person2 = (Person) person1.clone();
            System.out.println("Cloned: " + person2);
            // 修改原始对象中的地址,不影响克隆对象中的地址
            address.city = "Los Angeles";
            System.out.println("After modifying address:");
            System.out.println("Original: " + person1);
            System.out.println("Cloned: " + person2);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
 
输出:
Original: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
After modifying address:
Original: Person{name='John', age=30, address=Address{city='Los Angeles', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
 
6. 原型模式的优点
- 性能优化:当创建对象代价较高时,克隆可以比通过构造函数创建新对象更加高效。
 - 动态创建对象:原型模式允许在运行时动态地创建对象,而不需要知道具体的类或实现。
 - 减少子类数目:避免了频繁的使用子类去生成对象,通过克隆可以生成对象的不同版本。
 
7. 原型模式的缺点
- 深拷贝复杂:如果对象中有复杂的嵌套对象或循环引用,深拷贝的实现会非常复杂,需要逐层克隆每个引用的对象。
 - 依赖于具体的实现:克隆对象需要依赖类的 
clone()方法,可能会限制类的灵活性。 
8. 原型模式的应用场景
- 资源消耗大的对象创建:比如对象创建需要读取数据库、大量计算或需要访问网络资源时,可以使用原型模式进行克隆操作。
 - 重复创建相似对象:在某些系统中,需要频繁创建内容相似的对象,使用原型模式可以节省时间。
 - 不可变对象的场景:某些情况下,创建后不可修改的对象,原型模式可以保证对象的唯一性和一致性。
 
9. 总结
原型模式是一种有效的设计模式,适用于创建开销较大的对象。通过 clone() 方法,可以快速创建相同或类似的对象,减少创建新对象的成本。同时,它支持浅拷贝和深拷贝的灵活实现,在复杂的对象克隆场景下,深拷贝需要特别的设计。



















