前言
本系列博客仅是本人在复习中所记录
原型模式
定义:是一种对象型创建模式,通过复制原型实例来创建新的对象。
模式对象:
- 抽象原型类:定义克隆自己的方法的接口
- 具体原型类:实现具体的克隆业务,并返回一个新的克隆对象
- 客户类:定义一个原型对象,通过调用该对象的克隆方法来得到更多新的对象。
优点:
- 通过已有实例对象,提高新实例对象的创建过程的效率。
- 动态的增加或减少具体原型类
缺点:克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定容易。特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
实例说明:
场景:创建一个学生对象,对此对象进行克隆。
1、学生对象里不包含对象成员的克隆:
Student
/**
* 具体克隆类
* 其父类为Object 调用其clone方法
*/
public class Student implements Cloneable {
private String name;
private int age;
public Student(){}
public Student(String name,int age)
{
this.name=name;
this.age=age;
}
/**
* 普通成员下的克隆
* @return
*/
public Object cloneThis()
{
Object newObject=null;
try {
newObject=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newObject;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
/**
* 客户类
*/
public class Client {
public static void main(String[] args) {
Student s1=new Student("Tom",15);
Student s2=(Student)s1.cloneThis();
System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge());
System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge());
System.out.println("s1==s2?");
System.out.println(s1==s2);
/*结果如下:
s1_name:Tom s1_age:15
s2_name:Tom s2_age:15
s1==s2?
false
*/
}
}
2、学生对象里包含对象成员的克隆:
Student
import java.io.*;
/**
* 具体克隆类 Student
*/
public class Student implements Cloneable, Serializable {
private String name;
private int age;
private School school;
public Student(){}
public Student(String name,int age,School school)
{
this.name=name;
this.age=age;
this.school=school;
}
/**
* 对象成员下的浅克隆方法
* @return
*/
public Object shallowClone() throws CloneNotSupportedException
{
Object newObject=null;
try {
newObject=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newObject;
}
/**
* 对象成员下的深克隆方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object newObject=null;
try
{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
oos.flush();
oos.close();
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
newObject=ois.readObject();
ois.close();
}catch(Exception e)
{
e.printStackTrace();
}
return newObject;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public School getSchool() {
return school;
}
}
School
import java.io.Serializable;
/**
* 学校类
* 作为Student的成员
*/
public class School implements Cloneable, Serializable {
private String schoolName;
public School(){}
public School(String schoolName)
{
this.schoolName=schoolName;
}
public String getSchoolName()
{
return schoolName;
}
}
浅克隆
Client
/**
* 测试对象成员下的浅克隆
*/
public class Client {
public static void main(String[] args) {
School school=new School("光明中学");
Student s1=new Student("Mike",18,school);
Student s2= null;
try {
s2 = (Student)s1.shallowClone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge()+" s1_School"+s1.getSchool().getSchoolName());
System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge()+" s2_School"+s2.getSchool().getSchoolName());
System.out.println("s1==s2?");
System.out.println(s1==s2);
System.out.println("s1.school==s2.school?");
System.out.println(s1.getSchool()==s2.getSchool());
/**
* 结果如下:浅克隆对成员对象失败
*
* s1_name:Mike s1_age:18 s1_School光明中学
* s2_name:Mike s2_age:18 s2_School光明中学
* s1==s2?
* false
* s1.school==s2.school?
* true
*/
}
}
深克隆
/**
* 测试对象成员下的深克隆
*/
public class Deep_Client {
public static void main(String[] args) {
School school=new School("光明中学");
Student s1=new Student("Mike",18,school);
Student s2= null;
try {
s2 = (Student)s1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge()+" s1_School"+s1.getSchool().getSchoolName());
System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge()+" s2_School"+s2.getSchool().getSchoolName());
System.out.println("s1==s2?");
System.out.println(s1==s2);
System.out.println("s1.school==s2.school?");
System.out.println(s1.getSchool()==s2.getSchool());
/**
* 结果如下:对象成员深克隆成功
*
* s1_name:Mike s1_age:18 s1_School光明中学
* s2_name:Mike s2_age:18 s2_School光明中学
* s1==s2?
* false
* s1.school==s2.school?
* false
*/
}
}
此外原型模式还有两种扩展写法
-
添加原型管理类,定义HashTable类型的集合,使用“键值对”来存储原型对象,客户端可以通过Key来获取对应原型对象的的克隆对象。提供了增加原型对象的方法和获得克隆对象的方法。
-
相似对象的复制,对原型对象进行克隆以后,仅需要修改对象间的不同点。
参考书籍:
设计模式.刘伟.胡志刚.郭克华.清华大学出版社