用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
原型模式包含如下角色:
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(),我们得到的结果是原型对象创建了,并且非基本类型属性也重新创建了。这就是深拷贝。