3 . 示例代码 :
① 原型模式深拷贝示例 : 深拷贝与浅拷贝只是在 clone 方法中表现不同 , 其它代码一致 ; 在 clone 方法中需要针对引用类型进行克隆 ;
package kim.hsl.design.prototype.deepcopy; import java.util.Vector; /** * 浅拷贝示例 */ public class Student implements Cloneable { private String name; private int age; //该类在拷贝时 , 如果使用浅拷贝 , 只是将地址拷贝走了 , 两个对象实际上用的是同一个对象 private Vector<String> courses = new Vector<>(); public Student() { System.out.println("调用 Student 默认构造函数"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Vector<String> getCourses() { return courses; } public void setCourses(Vector<String> course) { this.courses = course; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", course=" + courses + '}'; } @Override protected Object clone() throws CloneNotSupportedException { System.out.println("调用 Student clone 方法"); //1 . 首先拷贝一个基本对象 Student student = (Student) super.clone(); //2 . 将引用类型的对象单独克隆赋值 student.courses = (Vector<String>) this.courses.clone(); //3 . 返回创建的新的对象 return student; } }
② 测试代码 :
package kim.hsl.design.prototype.deepcopy; public class Main { public static void main(String[] args) { try { //测试使用 clone 方法实现的原型模式 , 使用原型模式创建 2 个对象 Student newStudent = new Student(); // 1 . 使用 clone 方法创建对象1 Student student = (Student) newStudent.clone(); student.setName("Tom"); student.setAge(10); student.getCourses().add("数学"); // 2 . 使用 clone 方法创建对象2 Student student2 = (Student) newStudent.clone(); student2.setName("Jerry"); student2.setAge(18); student2.getCourses().add("语文"); System.out.println("student : " + student + "\nstudent2 : " + student2); } catch (CloneNotSupportedException e) { //捕获 clone 方法可能产生的异常 e.printStackTrace(); } } }
③ 运行结果 : 原型模式的两个实例对象的互不干扰 ;
调用 Student 默认构造函数 调用 Student clone 方法 调用 Student clone 方法 student : Student{name='Tom', age=10, course=[数学]} student2 : Student{name='Jerry', age=18, course=[语文]}
IV . 原型模式 与 单例
1 . 原型模式 与 单例模式 :
① 原型模式 : 原型模式的核心是不调用构造函数 , 使用 clone 方法在内存中克隆对象 ;
② 单例模式 : 单例模式的核心是私有化构造函数 , 控制外部用户 , 不能随意调用构造函数创建对象 ;
2 . Cloneable 破坏了单例模式 : 此处二者就出现了矛盾 , 如果单例类 , 实现了 Cloneable 接口 , 那么该类就可以调用 clone 方法创建另外的实例对象 , 因此破坏了单例模式 ;
3 . 解决方案 :
① 不实现 Cloneable 接口 : 单例模式中不要实现 Cloneable 接口 , 不提供内存拷贝功能 ;
② clone 中调用单例 : 如果必须实现 Cloneable 接口 , 那么在重写的 clone 方法中 , 调用获取单例类的方法 , 不要进行内存对象拷贝创建新的实例对象 ;
V . 原型模式 中的 final 关键字 ( 禁止出现 )
1 . final 作用 : final 用于修饰常量 , 被 final 修饰的变量无法重新赋值 ;
2 . Cloneable 实现类成员不要使用 final : 在原型模式的类中 , 实现了 Cloneable 接口 , 重写了 clone 方法 , 其类对象的成员不能被 final 修饰 , 否则无法重新赋值 ;