说明:本文是《大话设计模式》一书的学习文摘和网上相关信息文摘,原书代码例子用C#写,下面用Java改写。
1、原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
2、原型模式的UML类图
3、在Java中原型模式变成clone()方法的使用,由于Java的纯洁的面向对象特性,使得在Java中使用设计模式变得很自然,两者已经几乎是浑然一体了。
Java中对象的克隆:
(1)为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
(2)在派生类中覆盖基类的clone()方法,并声明为public。
(3)在派生类的clone()方法中,调用super.clone()。
(4)在派生类中实现Cloneable接口。
4、在Java中,clone()方法是浅复制。
浅复制(浅克隆) :被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深复制(深克隆) :被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
可以利用串行化来做深复制,所谓对象序列化就是将对象的状态转换成字节流,以后可以通过这些值再生成相同状态的对象。
5、下面实现一个简历的原型模式
package demo9;
import java.io.*;
/**
* 简历类
*
*/
public class Resume implements Serializable,Cloneable {
/**
*
*/
private static final long serialVersionUID = 8614140644886700330L;
private String name;
private String sex;
private Integer age;
private WorkExperience work;
public Resume(String name){
this.name = name;
work = new WorkExperience();
}
//设置个人信息
public void setPersonalInfo(String sex, Integer age){
this.sex = sex;
this.age = age;
}
//设置工作经历
public void setWorkExperience(String workDate,String company){
work.setWorkDate(workDate);
work.setCompany(company);
}
//显示
public void display(){
System.out.println(String.format("%s %s %s", name,sex,age));
System.out.println(String.format("工作经历:%s %s", work.getWorkDate(), work.getCompany()));
}
//浅复制
public Object clone(){
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
//深复制
public Object deepClone() throws IOException, ClassNotFoundException{
//将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
}
package demo9;
import java.io.Serializable;
/**
* 工作经历类
*
*/
public class WorkExperience implements Serializable {
private static final long serialVersionUID = -5461562344310808271L;
private String workDate;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
private String company;
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
package demo9;
import java.io.IOException;
/**
* 客户端调用
*
*/
public class Demo9 {
public static void main(String[] args) throws ClassNotFoundException, IOException {
Resume a = new Resume("大鸟");
a.setPersonalInfo("男", 29);
a.setWorkExperience("1998-2000", "xx公司");
//浅复制
Resume b = (Resume)a.clone();
b.setWorkExperience("1998-2006", "yy公司");
b.setPersonalInfo("男", 25);
a.display();
b.display();
// 运行结果:a和b的WorkExperience的引用值是一样的
// 大鸟 男 29
// 工作经历:1998-2006 yy公司
// 大鸟 男 25
// 工作经历:1998-2006 yy公司
Resume c = new Resume("大鸟");
c.setPersonalInfo("男", 29);
c.setWorkExperience("1998-2000", "xx公司");
//深复制
Resume d = (Resume)c.deepClone();
d.setWorkExperience("1998-2006", "yy公司");
d.setPersonalInfo("男", 25);
c.display();
d.display();
// 运行结果:a和b的WorkExperience的引用值是不同的
// 大鸟 男 29
// 工作经历:1998-2000 xx公司
// 大鸟 男 25
// 工作经历:1998-2006 yy公司
}
}