2.原型模式
(1).概述
用一个创建的实列作为原型,通过复制该原型对象来创建一个和原型都相同的新对象。
(2).结构
原型模式包含如下角色:
- 抽象原型类: 规定了具体原型对象必须实现的Clone()方法。
JDK帮我们做了
。 - 具体原型类: 实现抽象原型类的cone()方法,它是可以被复制的对象
- 访问类: 使用具体原型类中的clone()方法来复制新的对象。
(3).实现
原型模式的克隆分为浅克隆和深克隆
浅克隆
: 浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性,而不拷贝对象包含的引用指向的对象。)会指向原有对象的地址,内存地址一样
深克隆
: 深克隆:深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。不再指向原有对象的地址。
Java中的Object类
中提供了 clone()
方法来实现浅克隆
。Cloneable接口是上面的类图中的抽象原型类,而实现了cloneable接口的子实现类就是具体的原型类。
具体原型类: 这里我们继承coneable接口重写clone()方法实现克隆
package com.jsxs.pattern.prototype.demo; /** * @Author Jsxs * @Date 2023/4/18 13:23 * @PackageName:com.jsxs.pattern.prototype.demo * @ClassName: Realizetype * @Description: TODO * @Version 1.0 */ public class Realizetype implements Cloneable{ public Realizetype(){ System.out.println("具体的原型对象被创建了"); } // 1.重写方法 @Override public Realizetype clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功!!!"); return (Realizetype)super.clone(); } }
访问类
package com.jsxs.pattern.prototype.demo; /** * @Author Jsxs * @Date 2023/4/18 13:33 * @PackageName:com.jsxs.pattern.prototype.demo * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { // 1.创建一个原型类对象 Realizetype realizetype = new Realizetype(); // ->利用无参的构造方法去创建对象 //2.调用Realizetype类中我们重写的clone()方法进行对象的克隆 Realizetype clone = realizetype.clone(); System.out.println("原型对象和克隆的对象是否是同一个对象 "+(realizetype==clone)); } } • 1
(4).案列
用原型模式生成 "三好学生"奖状
同一学校的"三号学生"奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个:"三好学生"奖状出来,然后再修改奖状上的名字即可。
具体原型类: 这里我们继承coneable接口重写clone()方法实现克隆
package com.jsxs.pattern.prototype.demo2; /** * @Author Jsxs * @Date 2023/4/18 13:52 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Citation * @Description: TODO * @Version 1.0 */ public class Citation implements Cloneable{ // 基本属性 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } // 重写clone方法 @Override public Citation clone() throws CloneNotSupportedException { return (Citation)super.clone(); } public void show(){ System.out.println(name+"获得奖状一张!!"); } }
访问类
package com.jsxs.pattern.prototype.demo2; /** * @Author Jsxs * @Date 2023/4/18 13:54 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { // 1.原型对象的创建 Citation citation = new Citation(); citation.setName("李明-原型对象"); // 2.克隆对象 Citation clone = citation.clone(); clone.setName("吉士-克隆对象"); citation.show(); clone.show(); System.out.println(citation==clone); } }
(5).使用场景
- 对象的创建非常复杂,可以使用原型模式快捷的创建对象
- 性能和安全要求比较高
(6).扩展(深克隆)
将上面的"三好学生"奖状的案列中的name属性更改为Student类型的属性。
浅克隆
引用对象类
package com.jsxs.pattern.prototype.demo2; /** * @Author Jsxs * @Date 2023/4/18 14:22 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Student * @Description: TODO * @Version 1.0 */ public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
具体原型类
package com.jsxs.pattern.prototype.demo2; /** * @Author Jsxs * @Date 2023/4/18 13:52 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Citation * @Description: TODO * @Version 1.0 */ public class Citation implements Cloneable{ // 基本属性 private Student student; public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } // 重写clone方法 @Override public Citation clone() throws CloneNotSupportedException { return (Citation)super.clone(); } public void show(){ System.out.println(student.getName()+"获得奖状一张!!"); } }
访问类
package com.jsxs.pattern.prototype.demo2; /** * @Author Jsxs * @Date 2023/4/18 13:54 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { // 1.原型对象的创建 Citation citation = new Citation(); Student student = new Student(); student.setName("原型对象-张三"); citation.setStudent(student); // 2.克隆对象 Citation clone = citation.clone(); Student student1 = citation.getStudent(); student1.setName("克隆对象-李四"); clone.show(); citation.show(); System.out.println(student==student1); } }
说明: student和student1的对象是一个对象,就会产生studen1对象的属性会覆盖student的属性的效果。对具体原型类中的引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流。
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程
Student引用类-> 序列化
package com.jsxs.pattern.prototype.demo3; import java.io.Serializable; /** * @Author Jsxs * @Date 2023/4/18 14:22 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Student * @Description: TODO * @Version 1.0 */ public class Student implements Serializable { //序列化 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
具体克隆类 -> 序列化
package com.jsxs.pattern.prototype.demo3; import java.io.Serializable; /** * @Author Jsxs * @Date 2023/4/18 13:52 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Citation * @Description: TODO * @Version 1.0 */ public class Citation implements Serializable { // 基本属性 private Student student; public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public void show(){ System.out.println(student.getName()+"获得奖状一张!!"); } }
访问类
package com.jsxs.pattern.prototype.demo3; import java.io.*; /** * @Author Jsxs * @Date 2023/4/18 13:54 * @PackageName:com.jsxs.pattern.prototype.demo2 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client{ public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { // 1.原型对象的创建 Citation citation = new Citation(); Student student = new Student(); student.setName("原型对象-张三"); citation.setStudent(student); // 2.创建对象输出流对象 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("E:\\加速器\\a.txt")); out.writeObject(citation); //将原型对象写入文件中 out.close(); //关闭资源 ObjectInputStream ipt = new ObjectInputStream(new FileInputStream("E:\\加速器\\a.txt")); Citation citation1 = (Citation)ipt.readObject(); ipt.close(); //关闭资源 Student student1 = citation1.getStudent(); student.setName("克隆对象-李四"); citation.show(); citation1.show(); System.out.println(student==student1); } }