什么是原型模式
用已经创建的实例作为原型,通过复制该原型来创建新的对象.就像名人的影分身术一样简单.
深克隆与浅克隆
- 浅克隆
如果原型对象的成员变量是值类型(八大基本类型,byte,short,int,long,char,double,float,boolean).那么就直接复制,如果是复杂的类型,(枚举,String,对象)就只复制对应的内存地址。 - 深克隆
就是什么都是单独的!全部复制,然后各自独立。你修改克隆对象对于原型对象没有丝毫影响,完全的影分身!
原型模式的结构
原型模式包含三个主要角色:
- 抽象原则类: 具体原型对象必须实现的接口
- 具体原则类: 是可复制的对象,实现了抽象原则类的clone()方法
- 访问类: 使用具体原则类的clone()方法来克隆对象
//具体原型类
class Realizetype implements Cloneable
{
Realizetype()
{
System.out.println("具体原型创建成功!");
}
public Object clone() throws CloneNotSupportedException
{
System.out.println("具体原型复制成功!");
return (Realizetype)super.clone();
}
}
//原型模式的测试类
public class PrototypeTest
{
public static void main(String[] args)throws CloneNotSupportedException
{
Realizetype obj1=new Realizetype();
Realizetype obj2=(Realizetype)obj1.clone();
System.out.println("obj1==obj2?"+(obj1==obj2));
}
}
打印结果如下:
具体原型创建成功!
具体原型复制成功!
obj1==obj2?false
这里的Cloneable就是抽象原则类,提供了浅克隆方法.
浅克隆调用java的clone()方法,而深克隆通过序列化(Serialization)等方式来进行。
将附件类进行序列化.
package prototypePattern;
import java.io.Serializable;
public class Attachment_2 implements Serializable {
private String name; //附件名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void download() {
System.out.println("下载附件"+name);
}
}
周报类也进行序列化:
package prototypePattern;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
public class WeeklyLog_2 implements Serializable{
private Attachment_2 attachment;
private String date;
private String name;
private String content;
public Attachment_2 getAttachment() {
return attachment;
}
public void setAttachment(Attachment_2 attachment) {
this.attachment = attachment;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
//通过序列化进行深克隆
public WeeklyLog_2 deepclone() throws Exception {
//将对象写入流中,
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(this);
//将对象取出来
ByteArrayInputStream bi = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bi);
return (WeeklyLog_2)ois.readObject();
}
}
package prototypePattern;
public class Client_2 {
//测试类,客户端
public static void main(String[] args) {
WeeklyLog_2 log_1,log_2=null;
log_1 = new WeeklyLog_2(); //创建原型对象
Attachment_2 attachment = new Attachment_2(); //创建附件对象
log_1.setAttachment(attachment); //将附件添加到周报种去
try {
log_2=log_1.deepclone();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //克隆周报
System.out.println("周报对象是否相同"+(log_1==log_2));
System.out.println("附件对象是否相同"+(log_1.getAttachment()==log_2.getAttachment()));
}
}
周报对象是否相同:false
附件对象是否相同:false
注: final 类型修饰的成员变量不能进行深拷贝