设计模式---原型模式

80 阅读3分钟

原型模式

原型模式是一种创建型设计模式,它允许通过复制一个已有的对象来创建新的对象,而无需知道具体的类别。原型模式通过实现Cloneable接口,并重写clone()方法,在运行时动态地创建一个与原型对象相同的新对象。

在原型模式中,每个原型对象都可以被视为一个模板或蓝图,用于生成新的对象。当需要创建新的对象时,通过复制这个模板对象并修改其中的属性值,就可以快速地创建出一个全新的对象,而不必重新创建和初始化对象,从而提高了代码的效率和可维护性。

原型模式通常分为深拷贝浅拷贝两种类型。浅拷贝是指只复制基本数据类型和对象的引用,而不复制对象本身,因此多个对象可能会共享同一个引用,从而导致意外的副作用。深拷贝则是在复制对象时递归复制对象的所有子对象,并创建新的对象实例来存储复制的内容,从而确保每个对象都是独立的,互不干扰。

深拷贝:创建一个新的对象,属性中引用其他对象也会被克隆,不再指向原有对象地址

浅拷贝:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址

案例1.1

Person类,其中包含了姓名和出生日期两个属性:

/**
 * Person实现Cloneable接口,并重写了clone()方法以支持对象的复制。
 * */
public class Person implements Cloneable {
    private String name;
    private Date birthDate;

    public Person(String name, Date birthDate) {
        this.name = name;
        this.birthDate = birthDate;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    public String getName() {
        return name;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
}

在主函数中,我们可以创建一个原型对象并通过调用clone()方法来创建新的对象:

// 创建原型对象
Person person1 = new Person("张三", new Date());
// 使用克隆方法创建新的对象
Person person2 = person1.clone();

// 修改person2的属性值,不影响person1
person2.setName("李四");
person2.setBirthDate(new Date(2020, 1, 1));


System.out.println(person1 == person2);
System.out.println(person1);
System.out.println(person2);

image.png

赋值之后 拷贝出来的结果 (地址值不一样)

```
        // 创建原型对象
        Person person1 = new Person("张三", new Date());
        // 使用克隆方法创建新的对象
        Person person2 = person1.clone();

        // 修改person2的属性值,不影响person1
//        person2.setName("李四");
//        person2.setBirthDate(new Date(2020, 1, 1));


        System.out.println(person1 == person2);
        System.out.println(person1);
        System.out.println(person2);

        System.out.println(person1.getName().equals( person2.getName()));
        System.out.println(person1.getName());
        System.out.println(person2.getName());
        System.out.println(person1.getBirthDate() == person2.getBirthDate());
        System.out.println(person1.getBirthDate());
        System.out.println(person2.getBirthDate());
```

不赋值 拷贝出来的结果 (不同对象,地址值不一样,属性一样)

浅拷贝 学生案例


public class Student implements Cloneable {
    private String name;
    private int[] scores;

    public Student(String name, int[] scores) {
        this.name = name;
        this.scores = scores;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setScores(int[] scores) {
        this.scores = scores;
    }

    public String getName() {
        return name;
    }

    public int[] getScores() {
        return scores;
    }

    @Override
    public Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
}
public static void main(String[] args) throws CloneNotSupportedException {
    // 创建原型对象
    Student student1 = new Student("张三", new int[]{90, 85, 95});

    // 浅拷贝
    Student student2 = (Student) student1.clone();
    student2.setName("李四");
    student2.getScores()[0] = 100;

    // 输出结果
    System.out.println(student1.getName() + " " + Arrays.toString(student1.getScores()));  // 张三 [100, 85, 95]
    System.out.println(student2.getName() + " " + Arrays.toString(student2.getScores()));  // 张三 [100, 85, 95]
}

上边案例可以看出 对象中引用对象地址值是一样的

深拷贝 学生案例

image.png

在学生类中 修改这一行代码

image.png