原型设计模式
- 模式动机
- 模式定义
- 模式结构
- 模式分析
- 深拷贝和浅拷贝
- 原型模式实例与解析
- 实例一:邮件复制(浅克隆)
- 实例二:邮件复制(深克隆)
模式动机
在面向对象系统中,使用原型模式来复制一个对象自身,从而克隆出多个与原型对象一模一样的对象。
在软件系统中,有些对象的创建过程较为复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在。
模式定义
原型模式(Prototype Pattern):原型模式是一种对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式允许一个对象再创建另外一个可定制的对象,无须知道任何创建的细节。
原型模式的基本工作原理是通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝原型自己来实现创建过程。
模式结构
原型模式包含如下角色:
- Prototype:抽象原型类
- ConcretePrototype:具体原型类
- Client:客户类
模式分析
在原型模式结构中定义了一个抽象原型类,所有的Java类都继承自java.lang.Object,而Object类提供一个clone()方法,可以将一个Java对象复制一份。因此在Java中可以直接使用Object提供的clone()方法来实现对象的克隆,Java语言中的原型模式实现很简单。
能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持复制。如果一个类没有实现这个接口但是调用了clone()方法,Java编译器将抛出一个CloneNotSupportedException异常。
深拷贝和浅拷贝
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。clone明显是深复制,clone出来的对象是是不能去影响原型对象的
Java语言提供的clone()方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
(1) 对任何的对象x,都有x.clone() !=x,即克隆对象与原对象不是同一个对象。
(2) 对任何的对象x,都有x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。
(3) 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
原型模式实例与解析
实例一:邮件复制(浅克隆)
由于邮件对象包含的内容较多(如发送者、接收者、标题、内容、日期、附件等),某系统中现需要提供一个邮件复制功能,对于已经创建好的邮件对象,可以通过复制的方式创建一个新的邮件对象,如果需要改变某部分内容,无须修改原始的邮件对象,只需要修改复制后得到的邮件对象即可。使用原型模式设计该系统。在本实例中使用浅克隆实现邮件复制,即复制邮件(Email)的同时不复制附件(Attachment)。
public class Attachment
{
public void download()
{
System.out.println("Attachment");
}
}
public class Email implements Cloneable
{
private Attachment attachment=null;
public Email()
{
this.attachment=new Attachment();
}
public Object clone()
{
Email clone=null;
try
{
clone=(Email)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println("Clone failure!");
}
return clone;
}
public Attachment getAttachment()
{
return this.attachment;
}
public void display()
{
System.out.println("�鿴�ʼ�");
}
}
public class Client
{
public static void main(String a[])
{
Email email,copyEmail;
email=new Email();
copyEmail=(Email)email.clone();
System.out.println("email==copyEmail?");
System.out.println(email==copyEmail);
System.out.println("email.getAttachment==copyEmail.getAttachment?");
System.out.println(email.getAttachment()==copyEmail.getAttachment());
}
}
实例二:邮件复制(深克隆)
使用深克隆实现邮件复制,即复制邮件的同时复制附件。
import java.io.*;
public class Attachment implements Serializable
{
public void download()
{
System.out.println("���ظ���");
}
}
import java.io.*;
public class Email implements Serializable
{
private Attachment attachment=null;
public Email()
{
this.attachment=new Attachment();
}
public Object deepClone() throws IOException, ClassNotFoundException, OptionalDataException
{
//�����������
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bao);
oos.writeObject(this);
//�����������ȡ��
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return(ois.readObject());
}
public Attachment getAttachment()
{
return this.attachment;
}
public void display()
{
System.out.println("�鿴�ʼ�");
}
}
public class Client
{
public static void main(String a[])
{
Email email,copyEmail=null;
email=new Email();
try{
copyEmail=(Email)email.deepClone();
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("email==copyEmail?");
System.out.println(email==copyEmail);
System.out.println("email.getAttachment==copyEmail.getAttachment?");
System.out.println(email.getAttachment()==copyEmail.getAttachment());
}
}