设计模式-原型模式

原型模式

定义

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

模式的角色和类图

原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

类图

设计模式-原型模式

Cloneable接口只是一个标识,接口里面并没有任何方法。真正的clone方法在Object类中。

实现

具体代码如下:

public class User implements Cloneable, Serializable {
    private Person person;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public User(){
        System.out.println("原型对象创建完成");
    }
    @Override
    protected User clone() throws CloneNotSupportedException {
        return (User)super.clone();
    }
    public void show(){
        System.out.println("用户"+person.getName()+"正在工作!");
    }
}
public class Person implements Serializable {
    private String name;

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

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

    public String getName() {
        return name;
    }
}

使用测试代码测试:

public class MainTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Person person = new Person("张三");
        user.setPerson(person);
        User user1 = user.clone();
        System.out.println(user1 == user);
        System.out.println(user1.getPerson() == user.getPerson());
    }
}

结果:

原型对象创建完成
false
true

所以使用Obeject中的克隆方法得到的对象时一个新的对象。但是对象中的非基本类型属性是相等的,并没有重新创建。这就引出了原型模式的深拷贝浅拷贝

浅拷贝和深拷贝

定义

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

所以如果只是实现Object中的Clone方法后也没有重写,那么就是浅拷贝,对象中非基本类型的属性没有重新创建新对象。如果需要一个新的属性对象。可以重写clone方法。创建新的属性对象。这就是深拷贝
如实现深拷贝,可将clone方法重写,具体代码如下:

 @Override
    protected User clone() throws CloneNotSupportedException {
        User user = (User)super.clone();
        user.setPerson(new Person("新对象"));
        return user;
    }

测试结果:

原型对象创建完成
false
false

还有一种深拷贝就是通过对象流的方式读取已经写入文件中的对象。在单列模式中我们说到对象流对单列模式的破坏是一个道理。在没有readResovle方法的情况下,对象流读取对象时会返回一个全新的对象,并且是深拷贝后的对象,我们通过代码测试下。
具体代码如下:

public class MainTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Person person = new Person("张三");
        user.setPerson(person);


        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\lenovo\\Desktop\\cs.txt"));
        oos.writeObject(user);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\lenovo\\Desktop\\cs.txt"));
        User user1 = (User)(ois.readObject());
        ois.close();

        System.out.println(user.getPerson() == user1.getPerson());
        user.show();
        user1.getPerson().setName("李四");
        user1.show();


    }
}

结果:

原型对象创建完成
false
用户张三正在工作!
用户李四正在工作!

上述代码没有调用clone方法。就是通过对象流的readObject(),我们得到的结果是原型对象创建了,并且非基本类型属性也重新创建了。这就是深拷贝

上一篇:使用git的一般操作


下一篇:Git clone出现问题以及解决办法