用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
原型模式包含如下角色:
原型模式的克隆分为浅克隆和深克隆。
Java中的Object类中提供了 clone() 方法来实现浅克隆。
Cloneable 接口是上面的类图中的抽 象原型类,
而实现了Cloneable接口的子实现类就是具体的原型类。
代码如下:
具体原型类
/** * @author * @date 2021/11/30 23:12 * 具体的原型类 */ @Data public class Realizetype implements Cloneable { private Student student; public Realizetype() { System.out.println("具体原型类创建成功"); } @Override protected Realizetype clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功!"); return (Realizetype) super.clone(); } }
访问类(测试)
/** * @author * @date 2021/11/30 23:14 * 测试访问类 */ public class PrototypeTest { public static void main(String[] args) throws CloneNotSupportedException { Student student = new Student("zhangsan",18); Realizetype r1 = new Realizetype(); r1.setStudent(student); Realizetype r2 = r1.clone(); System.out.println(r2==r1);//false System.out.println(r1.getStudent()== r2.getStudent());//true } }
从打印结果来看,两个对象的成员属性student指向同一个地址,所以这种克隆方式属性浅克隆,
注意:Realizetype和Student类都要实现Serializable接口
/** * @author * @date 2021/12/1 0:01 * 序列化方式实现深克隆 */ public class SerializePrototypeTest { public static void main(String[] args) throws Exception{ Student student = new Student("zs",22); Realizetype r1 = new Realizetype(); r1.setStudent(student); //将对象序列化 写入到磁盘 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\文件下载\\a.txt")); oos.writeObject(r1); oos.close(); //反序列化 读取对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\文件下载\\a.txt")); Realizetype r2 = (Realizetype) ois.readObject(); ois.close(); System.out.println(r1==r2); System.out.println(r1.getStudent()==r2.getStudent());//false 没有指向同一个对象 } }
@Data @AllArgsConstructor @NoArgsConstructor public class Student implements Serializable,Cloneable { private String name; private Integer age; @Override protected Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } }
重写clone方法
/** * @author * @date 2021/11/30 23:12 * 具体的原型类 */ @Data public class Realizetype implements Cloneable , Serializable { private Student student; public Realizetype() { System.out.println("具体原型类创建成功"); } /** * 自定义clone方法实现深克隆 * @return * @throws CloneNotSupportedException */ @Override protected Realizetype clone() throws CloneNotSupportedException { //先对对象进行浅克隆 Realizetype realizetype = (Realizetype) super.clone(); //将成员属性设置成一个新的对象 把原来的值set进去 //或者成员属性也重写重写clone方法 我们使用clone方法复制即可 但是如果很深的话就很烦(成员对象内部又有自己的非基本类型成员对象) Student student = realizetype.getStudent();//目前执行同一个地址 Student newStu = student.clone(); realizetype.setStudent(newStu); return realizetype; } }
测试
/** * @author * @date 2021/11/30 23:14 * 测试访问类 */ public class PrototypeTest { public static void main(String[] args) throws CloneNotSupportedException { Student student = new Student("zhangsan",18); Realizetype r1 = new Realizetype(); r1.setStudent(student); Realizetype r2 = r1.clone(); System.out.println(r2==r1);//false System.out.println(r1.getStudent()== r2.getStudent());//false } }
观察测试结果 发现实现了深拷贝
对象的创建非常复杂,可以使用原型模式快捷的创建对象。
新对象和就对象的大部分属性都一样
性能和安全要求比较高。(无需新建对象再去一个一个set属性,clone是native方法,性能高)