Chapter 9 原型模式
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 简单的说就是clone一个对象实例。使得clone出来的copy和原有的对象一模一样。 插一个简单使用clone的例子,如果一个对象内部有可变对象实例的话,public API不应该直接返回该对象的引用,以防调用方的code改变该对象的内部状态。这个时候可以返回该对象的clone。 一般而言,我们要的clone应该是这样的。copy和原型的内容一样,但是又是彼此隔离的。即在clone之后,改变其中一个不影响另外一个。
原型模式分为浅复制和深复制,其中浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
class User { String name; int age; } class Account implements Cloneable { User user; long balance; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
我们之所以要深copy,是因为默认的实现提供的浅copy不是隔离的,换言之,改变copy的东西,会影响到原型的内部。比如例子中,改变copy的user的name,影响了原型。特别注意的是string是一种拥有值类型特点的特殊引用类型。
class User implements Cloneable { String name; int age; @Override public User clone() throws CloneNotSupportedException { return (User) super.clone(); } } class Account implements Cloneable { User user; long balance; @Override public Account clone() throws CloneNotSupportedException { Account account = null; account = (Account) super.clone(); if (user != null) { account.user = user.clone(); } return account; } }
再来贴2个实例代码
一、浅复制:
package xiao;
class WorkExp{
private String workDate;
private String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExp work;
public Resume(String name){
this.name = name;
work = new WorkExp();
}
public void setPerInfo(String sex,String age){
this.sex = sex;
this.age = age;
}
public void setWorkExper(String timeArea,String company){
work.setWorkDate(timeArea);
work.setCompany(company);
}
public void display(){
System.out.println(this.name+" "+this.sex+" "+this.age);
System.out.println(work.getWorkDate()+" "+work.getCompany());
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Hello {
public static void main(String[] args) throws Exception{
Resume a = new Resume("big bird");
a.setPerInfo("male", "20");
a.setWorkExper("1998-2006", "IT company");
Resume b = (Resume)a.clone();
b.setWorkExper("1998-2004", "YY company");
Resume c = (Resume)a.clone();
c.setPerInfo("female", "22");
c.setWorkExper("1998-2004", "ZZ company");
a.display();
b.display();
c.display();
}
}
输出:
big bird male 20
1998-2006 ZZ company
big bird male 20
1998-2004 ZZ company
big bird female 22
1998-2004 ZZ company
二、深复制:
package xiao;
class WorkExp implements Cloneable{
private String workDate;
private String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public WorkExp clone() throws CloneNotSupportedException {
return (WorkExp)super.clone();
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExp work;
public Resume(String name){
this.name = name;
work = new WorkExp();
}
public void setPerInfo(String sex,String age){
this.sex = sex;
this.age = age;
}
public void setWorkExper(String timeArea,String company){
work.setWorkDate(timeArea);
work.setCompany(company);
}
public void display(){
System.out.println(this.name+" "+this.sex+" "+this.age);
System.out.println(work.getWorkDate()+" "+work.getCompany());
}
public Resume clone() throws CloneNotSupportedException {
Resume resume = null;
resume = (Resume) super.clone();
if(work != null){
resume.work = work.clone();
}
return resume;
}
}
public class Hello {
public static void main(String[] args) throws Exception{
Resume a = new Resume("big bird");
a.setPerInfo("male", "20");
a.setWorkExper("1998-2006", "IT company");
Resume b = (Resume)a.clone();
b.setWorkExper("1998-2004", "YY company");
Resume c = (Resume)a.clone();
c.setPerInfo("female", "22");
c.setWorkExper("1998-2004", "ZZ company");
a.display();
b.display();
c.display();
}
}
输出:
big bird male 20
1998-2006 IT company
big bird male 20
1998-2004 YY company
big bird female 22
1998-2004 ZZ company