Java设计模式浅析
第一章 简单工厂模式
第二章 工厂方法模式
第三章 抽象工厂模式
第四章 单例模式
第五章 破坏单例模式
第六章 原型模式
第六章 原型模式
概述
原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,
并且通过拷贝这些原型创建新的对象。
所谓原型模式,就是 Java 中的克隆技术,以某个对象为原型,复制出新的对象。
显然新的对象具备原型对象的特点,效率高(避免了重新执行构造过程步骤)。
我们在设计后端代码的工程结构的时候会定义分层领域模型(VO、DTO、DO等),
Service 层调 Dao 层代码获取数据库数据,返回的对象模型是 DO,
在 Service 需要把 DO 对象转换为 VO 对象,这个时候就需要使用到原型模式。
● 类初始化消耗资源较多;
● 使用 new 产生一个对象需要非常繁琐的过程(数据准备、访问权限等);
● 构造函数比较复杂;
● 在循环体中生产大量对象。
一、浅克隆
示例代码
School
public class School {
private String schoolName;
public School() {
schoolName = new String("苏州小学");
}
// get set
public String getSchool() {
return schoolName;
}
}
Student 实现 Cloneable接口
public class Student implements Cloneable{
private String studentName;
private School school;
public Student() {
studentName = new String("张三");
school = new School();
}
@Override
protected Object clone() {
Student o = null;
try{
o = (Student)super.clone();
//需要捕获异常
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
//必须对其捕捉或者声明,以便抛出
//
//protected Object clone() throws CloneNotSupportedException {
//return super.clone();
//}
// get set
public String getSchool() {
return school.getSchool();
}
}
测试代码
public class PrototypeTest {
public static void main(String[] args) {
System.out.println("*************浅克隆*************");
Student s1 = new Student();
Student s2 = (Student) s1.clone();
System.out.println(s1 == s2);
System.out.println(s1.getSchool() == s2.getSchool());
System.out.println(s1.getSchool());
System.out.println(s2.getSchool());
}
}
二、深克隆
示例代码
School 实现Serializable 接口
import java.lang.*;
import java.io.*;
public class School implements Serializable {
private static final long serialVersionUID = 1L;
private String schoolName;
public School() {
schoolName = new String("苏州小学");
}
// get set
public String getSchool() {
return schoolName;
}
}
Student 实现的Cloneable接口、Serializable接口
public class Student implements Cloneable, Serializable {
//实现的Cloneable接口、Serializable接口
private static final long serialVersionUID = 1L;
private String studentName;
private School school;
public Student() {
studentName = new String("张三");
school = new School();
}
@Override
//浅拷贝
protected Object clone() {
Student o = null;
try{
o = (Student)super.clone();
//需要捕获异常
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
/**
* 利用序列化、反序列化实现深拷贝
*
* @return
* @throws Exception
*/
//深拷贝
public Student deepClone() {
Student o1 = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
o1 = (Student)ois.readObject();
}
catch(Exception e){
e.printStackTrace();
}
return o1;
}
// get set
public String getSchool() {
return school.getSchool();
}
}
测试代码
DeepClone
public class DeepClone {
public static void main(String[] args) {
System.out.println("*************深克隆*************");
Student s1 = new Student();
Student s2 = (Student) s1.deepClone();
System.out.println("s1、s2是否相等: "+ (s1 == s2) );
System.out.println("s1、s2 school equals 比较 : "+s1.getSchool().equals(s2.getSchool()));
//private String schoolName 所以不相等
System.out.println("s1、s2 school toString 比较 : "+s1.getSchool().toString()==s2.getSchool().toString());
//System.out.println(System.identityHashCode(s2.getSchool().toString()));
}
}
总结
对象克隆有如下实现方式:
● 继承 Cloneable 接口,实现 clone 方法
● 反射实现克隆,例子有 Apache BeanUtils、PropertyUtils,Spring BeanUtils
● 序列化实现克隆(字节流、JSON)
浅克隆
对值类型的成员变量进行值的复制,
对引用类型的成员变量仅仅复制引用,不复制引用的对象。
对应的实现方式有 Java clone、反射。