Chapter 9 原型模式

时间:2023-08-03 11:17:26

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 简单的说就是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();
}
}

Chapter 9 原型模式

我们之所以要深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;
}
}

Chapter 9 原型模式

再来贴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