lusiqi

设计模式-原型模式,介绍原型模式,及代码实现。


简介

原型模式用于创建重复的对象,同时又能保证性能,原型模式属于创建型模式。

分类

原型模式创建对象,可分为浅复制深复制

本文代码参考大话设计模式,即用java实现原型模式。需求:求职季,需要大量复制简历,这些简历大部分内容相同,可能有的简历有微微改动。

浅复制

浅复制是指:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

代码实现

简历类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* @description 简历类
* @author dxy
* @date 20200306
*/
public class Resume implements Cloneable, Serializable {

private static final long serialVersionUID = -4410449301166191440L;

private String name;
private String gender;
private int age;

// 引用“工作经历”对象,为演示深度拷贝和浅度拷贝而用
private WorkExperience workExperience;

public Resume() {
// 在“简历”类实例化时,同时实例化“工作经历”类
workExperience = new WorkExperience();
}

public void display() {
System.out.println(this.getName() + " " + this.getGender() + " "
+ this.getAge() + "\n工作经历: "
+ this.getWorkExperience().getWorkDate() + " "
+ this.getWorkExperience().getWorkCompany());
}

@Override
public Object clone() throws CloneNotSupportedException {

return super.clone();
}

public String getName() {
return name;
}

public Resume setName(String name) {
this.name = name;

return this;
}

public String getGender() {
return gender;
}

public Resume setGender(String gender) {
this.gender = gender;

return this;
}

public int getAge() {
return age;
}

public Resume setAge(int age) {
this.age = age;

return this;
}

public WorkExperience getWorkExperience() {
return workExperience;
}

public void setWorkExperience(String workDate, String workCompany) {
workExperience.setWorkDate(workDate);
workExperience.setWorkCompany(workCompany);
}
}

工作经历类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @description 工作经历类,为演示浅度拷贝而用
* @author dxy
* @date 20200306
*/
public class WorkExperience implements Serializable {

private static final long serialVersionUID = 1L;

private String workDate;
private String workCompany;

public String getWorkDate() {
return workDate;
}

public WorkExperience setWorkDate(String workDate) {
this.workDate = workDate;

return this;
}

public String getWorkCompany() {
return workCompany;
}

public WorkExperience setWorkCompany(String workCompany) {
this.workCompany = workCompany;

return this;
}

}

客户端类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* @description 原型模式客户端 演示浅度拷贝
* @author dxy
* @date 20200306
*/
public class PrototypeClient {



public static void main(String[] args) throws CloneNotSupportedException {

Resume a = new Resume();
a.setName("lusiqi").setGender("男 ").setAge(25);
a.setWorkExperience("2016-2020, ", "XX公司");

Resume b = (Resume) a.clone();
b.setWorkExperience("2016-2020, ", "YY公司");

Resume c = (Resume) a.clone();
c.setWorkExperience("2016-2020, ", "ZZ公司");

System.out.println("**********浅度拷贝:");
a.display();
b.display();
c.display();

}

}

结果:

1
2
3
4
5
6
7
**********浅度拷贝:
lusiqi 男 25
工作经历: 2016-2020, ZZ公司
lusiqi 男 25
工作经历: 2016-2020, ZZ公司
lusiqi 男 25
工作经历: 2016-2020, ZZ公司

浅度拷贝只能复制值属性,引用属性都指向相同的对象。

深度复制

深度复制在复制对象的所有值变量的同时,也会把引用对象的变量值指向复制过来的新对象,而不是原有的被引用的对象。

代码用两种方式实现:

  1. 简历的引用属性也实现Cloneable接口,即在克隆简历对象的同时,也克隆简历对象的引用属性工作经历对象。从而完成深度复制。
  2. 通过对象序列化,将对象写入流内,从流内读出对象,实现深度拷贝。
代码实现

简历类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* @description 简历类
* @author dxy
* @date 20200306
*/
public class Resume implements Cloneable, Serializable {

private static final long serialVersionUID = -4410449301166191440L;

private String name;
private String gender;
private int age;

// 引用“工作经历”对象,为演示深度拷贝和浅度拷贝而用
private WorkExperience workExperience;

public Resume() {
// 在“简历”类实例化时,同时实例化“工作经历”类
workExperience = new WorkExperience();
}

public Resume(WorkExperience workExperience) throws CloneNotSupportedException {
// 在“简历”类实例化时,同时实例化“工作经历”类
this.workExperience = (WorkExperience)workExperience.clone();
}

public void display() {
System.out.println(this.getName() + " " + this.getGender() + " "
+ this.getAge() + "\n工作经历: "
+ this.getWorkExperience().getWorkDate() + " "
+ this.getWorkExperience().getWorkCompany());
}

@Override
public Object clone() throws CloneNotSupportedException {

Resume obj = new Resume(this.workExperience);
obj.setAge(this.age);
obj.setGender(this.gender);
obj.setName(this.name);

return obj;
}

// 通过对象序列化,实现深度拷贝
public Object deepClone() throws IOException, ClassNotFoundException {
// 将对象写入流内
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);

// 从流内读出对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
bos.toByteArray()));
return ois.readObject();

}

public String getName() {
return name;
}

public Resume setName(String name) {
this.name = name;

return this;
}

public String getGender() {
return gender;
}

public Resume setGender(String gender) {
this.gender = gender;

return this;
}

public int getAge() {
return age;
}

public Resume setAge(int age) {
this.age = age;

return this;
}

public WorkExperience getWorkExperience() {
return workExperience;
}

public void setWorkExperience(String workDate, String workCompany) {
workExperience.setWorkDate(workDate);
workExperience.setWorkCompany(workCompany);
}
}

工作经历类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* @description 工作经历类,为演示深度拷贝和浅度拷贝而用
* @author dxy
* @date 20200306
*/
public class WorkExperience implements Cloneable,Serializable {

private static final long serialVersionUID = 1L;

private String workDate;
private String workCompany;

public String getWorkDate() {
return workDate;
}

public WorkExperience setWorkDate(String workDate) {
this.workDate = workDate;

return this;
}

public String getWorkCompany() {
return workCompany;
}

public WorkExperience setWorkCompany(String workCompany) {
this.workCompany = workCompany;

return this;
}

@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}

}

客户端类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @description 原型模式客户端 演示深度拷贝
* @author dxy
* @date 20200306
*/
public class PrototypeClient {


public static void main(String[] args) throws CloneNotSupportedException,
ClassNotFoundException, IOException {

Resume aResume = new Resume();
aResume.setName("lusiqi").setGender("男 ").setAge(25);
aResume.setWorkExperience("2016-2020, ", "XX公司");

Resume bResume = (Resume) aResume.clone();
bResume.setWorkExperience("2016-2020, ", "YY公司");

Resume cResume = (Resume) aResume.clone();
cResume.setWorkExperience("2016-2020, ", "ZZ公司");

Resume dResume = (Resume) aResume.deepClone();
dResume.setWorkExperience("2016-2020, ", "DD公司");

aResume.display();
bResume.display();
cResume.display();
dResume.display();


}

}

结果:

1
2
3
4
5
6
7
8
lusiqi 男  25
工作经历: 2016-2020, XX公司
lusiqi 男 25
工作经历: 2016-2020, YY公司
lusiqi 男 25
工作经历: 2016-2020, ZZ公司
lusiqi 男 25
工作经历: 2016-2020, DD公司

深度复制在复制对象的所有值变量的同时,也会把引用对象的变量值指向复制过来的新对象。

 评论