原型模式:就是通过原来的对象克隆一个跟自己一样的对象。
在java中只需要改对象 重写clone方法就可以在内存中创建一个新的对象,改新的对象与原来的对象的内存地址是不一样的。
克隆分为浅克隆还是深克隆
浅克隆:就是将原来对象的基本类型的属性复制到新的对象中去,但是引用类型的变量不会复制。
深克隆:该对象需要implements Serializable接口,这个对象的所有属性都可以克隆到新的对象中去。
举例,第一个是属性只有基本类型的。第二个例子是属性有一个引用类型的。
package prototype;
public class WeeklyLog implements Cloneable{
private String name;
private String date;
private String content;
public void setName(String name) {
this.name = name;
}
public void setDate(String date) {
this.date = date;
}
public void setContent(String content) {
this.content = content;
}
public String getName() {
return (this.name);
}
public String getDate() {
return (this.date);
}
public String getContent() {
return (this.content);
}
//克隆方法clone(),此处使用Java语言提供的克隆机制
public WeeklyLog clone()
{
Object obj = null;
try
{
obj = super.clone();
return (WeeklyLog)obj;
}
catch(CloneNotSupportedException e)
{
System.out.println("不支持复制!");
return null;
}
}
}
package prototype;
/*
* 注意clone的对象在内存内存中的地址是不一样的。
* */
public class Client {
public static void main(String args[])
{
WeeklyLog log_previous = new WeeklyLog(); //创建原型对象
log_previous.setName("张无忌");
log_previous.setDate("第12周");
log_previous.setContent("这周工作很忙,每天加班!");
System.out.println("****周报****");
System.out.println("周次:" + log_previous.getDate());
System.out.println("姓名:" + log_previous.getName());
System.out.println("内容:" + log_previous.getContent());
System.out.println("--------------------------------");
WeeklyLog log_new;
log_new = log_previous.clone(); //调用克隆方法创建克隆对象
log_new.setDate("第13周");
System.out.println("****周报****");
System.out.println("周次:" + log_new.getDate());
System.out.println("姓名:" + log_new.getName());
System.out.println("内容:" + log_new.getContent());
//System.out.println(log_previous.equals(log_new));
//System.out.println(log_previous==log_new);
System.out.println(log_previous == log_new);
System.out.println(log_previous.getDate() == log_new.getDate());
System.out.println(log_previous.getName() == log_new.getName());
System.out.println(log_previous.getContent() == log_new.getContent());
}
}
false
false
true
true
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
package prototypedeepclone;
import java.io.ByteArrayInputStream;
public class WeeklyLog implements Serializable,Cloneable{
private Attachment attachment;
private String name;
private String date;
private String content;
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public void setName(String name) {
this.name = name;
}
public void setDate(String date) {
this.date = date;
}
public void setContent(String content) {
this.content = content;
}
public Attachment getAttachment(){
return (this.attachment);
}
public String getName() {
return (this.name);
}
public String getDate() {
return (this.date);
}
public String getContent() {
return (this.content);
}
//使用序列化技术实现深克隆
public WeeklyLog 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 (WeeklyLog)ois.readObject();
}
}
package prototypedeepclone;
import java.io.Serializable;
public class Attachment implements Serializable{
private String name; //附件名
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
public void download()
{
System.out.println("下载附件,文件名为" + name);
}
}
package prototypedeepclone;
/*
* ava语言提供的Cloneable接口和Serializable接口的代码非常简单,它们都是空接口,这种空接口也称为标识接口,
* 标识接口中没有任何方法的定义,其作用是告诉JRE这些接口的实现类是否具有某个功能,
* 如是否支持克隆、是否支持序列化等。 *
* */
public class Client {
public static void main(String args[])
{
WeeklyLog log_previous, log_new = null;
log_previous = new WeeklyLog(); //创建原型对象
Attachment attachment = new Attachment(); //创建附件对象
log_previous.setAttachment(attachment); //将附件添加到周报中
try
{
log_new = log_previous.deepClone(); //调用深克隆方法创建克隆对象
}
catch(Exception e)
{
System.err.println("克隆失败!");
}
//比较周报
System.out.println("周报是否相同? " + (log_previous == log_new));
//比较附件
System.out.println("附件是否相同? " + (log_previous.getAttachment() == log_new.getAttachment()));
}
}