原型模式:
所谓的原型模式就是制造出原型对象的副本,副本对象的信息与原对象一致但是却在内存中占用不同的空间。
//下面是对原型模式应用实例:某公司需要产生许多信息大致相同的报表,但是报表少量的部分还是需要进行修改的,有需要对报表的修改不会影响到其他的报表信息。
//通用的原型设计思想
public class ReportForm implements Cloneable
{
private String name;//报表的名称
private String date;//报表的时间
private String content;//报表的内容
public ReportForm(String name, String date, Stringcontent)
{
super();
this.name = name;
this.date = date;
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString()
{
return "ReportForm:"+this.hashCode()+" date="+date+"name="+name+" content="+content;
}
public ReportForm clone()
{
ReportFormform = new ReportForm(this.name,this.date, this.content);
return form;
}
}
//Java特有的克隆模式
public class ReportForm implements Cloneable
{
private String name;//报表的名称
private String date;//报表的时间
private String content;//报表的内容
public ReportForm(String name, String date, Stringcontent)
{
super();
this.name = name;
this.date = date;
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString()
{
return "ReportForm:"+this.hashCode()+" date="+date+"name="+name+" content="+content;
}
public ReportForm clone()
{
Objectobject;
try {
object = super.clone();
return(ReportForm) object;
} catch(CloneNotSupportedException e) {
e.printStackTrace();
System.out.println("不能产生原型对象...");
}
return null;
}
}
//客户使用原型模式:
public class Client
{
public static void main(String[] args)
{
ReportForm form = new ReportForm("工作报表","第一周", "这是一份工作报表");
ReportForm new_form = form.clone();
new_form.setDate("第二周");
System.out.println(form);
System.out.println("-----------------------------------------------------------------------");
System.out.println(new_form);
}
}
结果(很显然客户对报表副本的修改并没有改变原型对象,那么这种设计是可行的)
ReportForm:33311724 date=第一周 name=工作报表 content=这是一份工作报表
-----------------------------------------------------------------------
ReportForm:14452073 date=第二周 name=工作报表 content=这是一份工作报表
//以上通过两种方式创建原型对象的副本,但是结果都是一样的,只是创建对象的思想变了。
注意:此时用户的需求变了,不仅只有单纯的报表,在报表之后还需要加附件,也就是在报表类中需要加入引用类型的对象变量。
Java中引用类型的变量并不能在克隆的时候产生一个副本,那么就需要用到深拷贝技术来实现
下面是相关代码(注:java中只要被拷贝的对象都要实现Cloneable接口)
//附件类
public class Attachment implements Cloneable
{
private String name;//附件的名称
public Attachment(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void download()
{
System.out.println(name+"附件被下载...");
}
public Attachment clone()
{
try {
return(Attachment)super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
System.out.println("不能创建原型对象...");
return null;
}
}
}
//原型类
public class ReportForm implements Cloneable
{
private String name;//报表的名称
private String date;//报表的时间
private String content;//报表的内容
private Attachment attachment;//需要被添加的附件
public ReportForm(String name, String date, Stringcontent,
Attachment attachment) {
super();
this.name = name;
this.date = date;
this.content = content;
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
@Override
public String toString()
{
return "ReportForm:"+this.hashCode()+" date="+date+"name="+name+" content="+content
+" attachment:"+attachment.hashCode()+" name="+attachment.getName();
}
public ReportForm clone()
{
ReportFormobj = null;
try
{
obj =(ReportForm)super.clone();
Attachmentobj2 = attachment.clone();
obj.setAttachment(obj2);
}
catch(CloneNotSupportedException e)
{
e.printStackTrace();
System.out.println("不能创建原型对像...");
}
return obj;
}
}
结果:
ReportForm:14452073 date=第一周 name=工作报表 content=这是一份工作报表 attachment:29013258 name=附件一
-----------------------------------------------------------------------
ReportForm:12830537 date=第一周 name=工作报表 content=这是一份工作报表 attachment:22068557 name=附件一
很显然这里的附件的引用也是不一样的,实现深拷贝也成功了。
//第二种进行深拷贝的方式
就是讲要拷贝的对象写入到流中,在将流中的对象进行重构形成新的对象
public ReportForm clone()
{
//将该对象写入流中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//重构流中的对象
ObjectInputStream ois = new ObjectInputStream(newByteArrayInputStream(bos.toByteArray()));
ReportForm form = (ReportForm)ois.readObject();
return form;
}
catch (Exceptione) {
e.printStackTrace();
System.out.println("不能重构对象...");
}
return null;
}
结果:
ReportForm:20688146 date=第一周 name=工作报表 content=这是一份工作报表 attachment:23276589(打印的是该对象的hashCode) name=附件一
-----------------------------------------------------------------------
ReportForm:16602326 date=第一周 name=工作报表 content=这是一份工作报表 attachment:30191657 name=附件一