原型模式是一种创建型设计模式,它允许一个对象创建另一个可定制的对象,而无需了解如何创建这个对象的细节。这种模式的核心在于对象拷贝,即通过将一个原型对象传给要创建的对象,然后由这个要创建的对象通过请求原型对象拷贝自身来实施创建。
本期代码:小麻雀icknn/设计模式练习 - Gitee.com
Java中Object类是所有类的根类,Object 类提供了一个clone()方法,该方法可以将一一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对像拷贝它们自己来实现创建,即对象的clone()

例子:
克隆源
- package com.study.main.Prototype;
-
- public class CloneSource implements Cloneable{
-
- public String getName() {
- return "克隆源";
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- CloneSource cloneSource = null;
- try{
- cloneSource = (CloneSource) super.clone();
- }
- catch (CloneNotSupportedException err){
- err.printStackTrace();
- }
- return cloneSource;
- }
- }
克隆1类
- package com.study.main.Prototype;
-
- public class CloneTest1 extends CloneSource{
- public void show(){
- System.out.println("测试克隆1");
- }
- }
克隆2类
- package com.study.main.Prototype;
-
- public class CloneTest2 extends CloneSource{
- public void show(){
- System.out.println("测试克隆2");
- }
- }
实现类
目标:克隆出2个克隆1类,2个克隆类
- package com.study.main.Prototype;
-
- public class PrototypeMain {
- public static void main(String[] args) throws CloneNotSupportedException {
- CloneTest1 cloneSource = new CloneTest1();
- CloneTest2 cloneSource2 = new CloneTest2();
- for (int i = 0; i < 2; i++) {
- CloneTest1 cloneTest= (CloneTest1) cloneSource.clone();
- cloneTest.show();
- System.out.println(cloneTest.getName());
- }
- for (int i = 0; i < 2; i++) {
- CloneTest2 cloneTest2= (CloneTest2) cloneSource2.clone();
- cloneTest2.show();
- System.out.println(cloneTest2.getName());
- }
- }
- }
结果:

注意 :
浅贝 是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
例子:
学生类:
- package com.study.main.Prototype.Test;
-
- public class Student implements Cloneable {
- String name;
- private Teacher teacher;
-
- public Teacher getTeacher() {
- return teacher;
- }
-
- public void setTeacher(Teacher teacher) {
- this.teacher = teacher;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Student student = null;
- try{
- Student clone = (Student) super.clone();
- return clone;
- }catch (CloneNotSupportedException err) {
- err.printStackTrace();
- }
- return student;
- }
- }
教师类
- package com.study.main.Prototype.Test;
-
- public class Teacher implements Cloneable {
- String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Teacher teacher = null;
-
- try{
- Teacher clone = (Teacher) super.clone();
- return clone;
- }catch (CloneNotSupportedException err) {
- err.printStackTrace();
- }
- return teacher;
- }
- }
测试&运行
- package com.study.main.Prototype.Test;
-
- public class TestMain {
- public static void main(String[] args) throws CloneNotSupportedException {
- // 创建教师
- Teacher teacher = new Teacher();
- // 设置教师姓名
- teacher.setName("A");
- // 创建学生
- Student stu1 = new Student();
- // 设置学生1教师
- stu1.setTeacher(teacher);
- // 克隆学生1==>学生2
- Student stu2 = (Student) stu1.clone();
- // 设置学生2教师
- stu2.setTeacher(teacher);
- // 获取stu2老师
- Teacher stu2Teacher = stu2.getTeacher();
- // 学生2改变名字
- teacher.setName("B");
- System.out.println("学生1老师姓名:"+stu1.getTeacher().getName());
- System.out.println("学生2老师姓名:"+stu2.getTeacher().getName());
- }
- }
结果

深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且”修改新对象不会影响原对象。
只改变上面学生类中的克隆方法让教师对象也进行一边克隆即可

完整学生类
- package com.study.main.Prototype.Test;
-
- public class Student implements Cloneable {
- String name;
- private Teacher teacher;
-
- public Teacher getTeacher() {
- return teacher;
- }
-
- public void setTeacher(Teacher teacher) {
- this.teacher = teacher;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Student student = null;
- try{
- Student clone = (Student) super.clone();
- teacher = (Teacher) this.teacher.clone();
- return clone;
- }catch (CloneNotSupportedException err) {
- err.printStackTrace();
- }
- return student;
- }
- }
结果:

附加Typescript版本
- interface Cloneable{
- clone():any;
- }
- class Student implements Cloneable{
- public name:string|undefined;
- public age:number|undefined;
- constructor(name:string,age:number){
- this.name = name;
- this.age = age;
- }
- public setName(name:string){
- this.name = name
- }
- clone(): any {
- const student:Object =new Object;
- const that = this;
- Object.assign(student,that)
- return student?student:new Error("创建失败");
- }
- }
- const stu1 = new Student('ycw',10);
- const stu2:Student = stu1.clone();
- stu1.setName("abc")
- console.log(stu1,"stu1")
- console.log(stu2,"stu2")

ArrayList
ArrayList 中实现了Cloneable接口
重写clone方法 copyof elementData
HashMap
HashMap也实现了Cloneable接口