设计模式--创建型--原型模式
- 原型模式
- 概述
- 结构
- 实现
- 结果
- 案例
- 代码
- 结果
- 使用场景
- 扩展(深\浅克隆)
- 浅克隆演示:
- 结果:
- 使用深克隆(利用对象流)
- 结果
原型模式
概述
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
结构
原型模式包含如下角色
- 抽象原型类:规定了具体原型对象必须实现的clone()方法
- 具体原型类:实现抽象原型的clone()方法,它是可被复制的对象。
- 访问类:使用具体原型类中的clone()方法来复制新的对象。
实现
原型模式的克隆分为浅克隆和深克隆。
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不在指向原有对象地址。
Java中的Object类中提供了clone()方法来实现浅克隆。
/*** 具体的原型类实现Cloneable接口 这里用Cloneable接口来当做抽象原型类*/
public class RealizeType implements Cloneable{public RealizeType(){System.out.println("使用构造器创建具体的原型对象");};/*** 重写clone()方法* @return RealizeType*/@Overridepublic RealizeType clone() throws CloneNotSupportedException{System.out.println("clone具体原型对象成功");return (RealizeType) super.clone();}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 创建一个原型对象RealizeType realizeType = new RealizeType();// 调用RealizeType中的clone方法进行对象的克隆RealizeType clone = realizeType.clone();System.out.println("原型对象和克隆对象是否是同一个对象?"+ (clone == realizeType));}
}
结果
案例
用原型模式生成"三好学生"奖状
奖状除了获奖人信息不同,其他都相同,可以使用原型模式复制多个“三好学生奖状”,然后修改学生信息即可
代码
public class Citation implements Cloneable{private String name;public String getName(){return name;}public void setName(String name){this.name = name;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(name + "同学的奖状");}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 创建奖状原型Citation citation = new Citation();citation.setName("张三");Citation clone = citation.clone();clone.setName("李四");citation.info();clone.info();}
}
结果
- 这里虽然是浅拷贝但是name属性没有改变,是因为name是String类型,如果是引用类型并且还是浅拷贝,那么原型对象中的name是改变的,下面是深、浅克隆演示。
使用场景
- 对象的创建非常复杂,可以使用原型模式快捷的创建对象
- 性能和安全的要求比较高
扩展(深\浅克隆)
这里将上面的name属性放到一个student对象中,而Citation类中的Student属性就是引用属性
浅克隆演示:
public class Citation implements Cloneable{private Student stu;public Student getStu(){return stu;}public void setStu(Student stu){this.stu = stu;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(stu.getName() + "同学的奖状");}
}
public class Student {private String name;public String getName(){return name;}public void setName(String name){this.name = name;}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 创建奖状原型Citation citation = new Citation();// 创建学生对象Student student = new Student();student.setName("张三");citation.setStu(student);citation.info();// 克隆Citation clone = citation.clone();// 重新设置学生姓名clone.getStu().setName("李四");citation.info();clone.info();}
}
结果:
说明:原型对象和克隆出来的对象中的student对象是同一个对象,修改其中一个,另一个的值也会改变。
这就是浅克隆的效果,对具体原型类中的引用数据类型进行引用的复制。
使用深克隆(利用对象流)
克隆时先将原型对象写入文件中,再读取。
public class Citation implements Cloneable, Serializable {private Student stu;public Student getStu(){return stu;}public void setStu(Student stu){this.stu = stu;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(stu.getName() + "同学的奖状");}
}
public class Student implements Serializable {private String name;public String getName(){return name;}public void setName(String name){this.name = name;}
}
public class Test02 {public static void main(String[] args) throws Exception {// 创建奖状原型Citation citation = new Citation();// 创建学生对象Student student = new Student();student.setName("张三");citation.setStu(student);citation.info();// 创建对象输出流对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:/a.txt"));// 写对象oos.writeObject(citation);// 释放oos.close();// 创建对象输入流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:/a.txt"));// 读取对象Citation citation1 = (Citation) ois.readObject();ois.close();citation1.getStu().setName("李四");citation.info();citation1.info();}
}