原型模式:(复制对象)
1.复制"引用"与复制"对象"的区别
1.1复制"引用"---复制地址
假设被复制对象为A a,复制的新对象为A b.
复制引用的过程就是将a的地址值复制给b.a和b同时指向堆内存的同一个地址.
过程为:
1 A a = new A();
2 A b = a;
这样,只要其中一个对象的属性发生变化,另一个对象的属性也随之发生变化.

根据"复制引用"编写程序:
1 public class Student {
2
3 public static void main(String[] args) {
4 Student s1 = new Student("张三", 23);
5 Student s2 = s1;
6 System.out.println(s1 == s2);
7 System.out.println(s1);
8 System.out.println(s2);
9
10 //1.改变s1的名字
11 s1.setName("李四");
12 System.out.println(s1 == s2);
13 System.out.println(s1);
14 System.out.println(s2);
15
16 //1.改变s1的名字
17 s2.setName("王五");
18 System.out.println(s1 == s2);
19 System.out.println(s1);
20 System.out.println(s2);
21 }
22
23 private String name;
24 private int age;
25
26 public Student() {}
27
28 public Student(String name, int age) {
29 this.name = name;
30 this.age = age;
31 }
32
33 public String getName() {
34 return name;
35 }
36
37 public void setName(String name) {
38 this.name = name;
39 }
40
41 public int getAge() {
42 return age;
43 }
44
45 public void setAge(int age) {
46 this.age = age;
47 }
48
49 @Override
50 public String toString() {
51 return "Student [name=" + name + ", age=" + age + "]";
52 }
53 }
程序运行结果:
1 true
2 Student [name=张三, age=23]
3 Student [name=张三, age=23]
4
5 true
6 Student [name=李四, age=23]
7 Student [name=李四, age=23]
8
9 true
10 Student [name=王五, age=23]
11 Student [name=王五, age=23]
1.2复制"对象"---复制内容
假设被复制对象为Student s1,复制的新对象为Student s2.
Student类有两个属性,name 和 age;
复制对象的过程:
①:Student s1 = new Student("张三", 23);
②:Student s2 = new Student();
③:s2.setName(s1.getName());
s2.setAge(s1.getAge());
s1与s2是两个不同的对象,保存相同的属性及其属性值.当s1的属性值发生变化时,s2的属性值不会受到影响.s1与s2相互独立.

根据"复制对象的过程"编写程序:
1 public class Student {
2
3 public static void main(String[] args) {
4 Student s1 = new Student("张三", 23);
5 Student s2 = new Student();
6
7 s2.setName(s1.getName());
8 s2.setAge(s1.getAge());
9 System.out.println(s1 == s2);
10 System.out.println(s1);
11 System.out.println(s2);
12
13 s1.setName("李四");
14 System.out.println(s1);
15 System.out.println(s2);
16
17 s2.setName("王五");
18 System.out.println(s1);
19 System.out.println(s2);
20 }
21
22 private String name;
23 private int age;
24
25 public Student() {}
26
27 public Student(String name, int age) {
28 this.name = name;
29 this.age = age;
30 }
31
32 public String getName() {
33 return name;
34 }
35
36 public void setName(String name) {
37 this.name = name;
38 }
39
40 public int getAge() {
41 return age;
42 }
43
44 public void setAge(int age) {
45 this.age = age;
46 }
47
48 @Override
49 public String toString() {
50 return "Student [name=" + name + ", age=" + age + "]";
51 }
52 }
程序运行结果:
1 false
2 Student [name=张三, age=23]
3 Student [name=张三, age=23]
4
5 Student [name=李四, age=23]
6 Student [name=张三, age=23]
7
8 Student [name=李四, age=23]
9 Student [name=王五, age=23]
2.原型模式
2.1假设对象的属性特征很简单:(直接赋值,不需要new对象来赋值)
例:情况1.
1 class Person{
2 private String name;
3 private int age;
4 }
那么:实现对象复制的过程很简单.
思路A:
①:Person类实现Cloneable接口.
Cloneable是一个标识性接口,没有抽象方法.实现这个接口的类被标记为可以被克隆.
②:Person类重写clone()方法.
根据思路A编写程序:
1 public class Person implements Cloneable{
2
3 public static void main(String[] args) throws CloneNotSupportedException {
4 // 测试
5 //原型
6 Person person = new Person("张三", 23);
7 //克隆对象
8 Person clonePerson = (Person)person.clone();
9 System.out.println(person == clonePerson);
10 System.out.println(person);
11 System.out.println(clonePerson);
12
13 //1.改变person的名字和对象
14 person.setName("李四");
15 person.setAge(24);
16 System.out.println(person);
17 System.out.println(clonePerson);
18
19 //2.改变clonePerson的名字和对象
20 clonePerson.setName("王五");
21 clonePerson.setAge(25);
22 System.out.println(person);
23 System.out.println(clonePerson);
24 }
25
26 private String name;
27 private int age;
28 public Person(String name, int age) {
29 this.name = name;
30 this.age = age;
31 }
32 public Person() {}
33 public String getName() {
34 return name;
35 }
36 public void setName(String name) {
37 this.name = name;
38 }
39 public int getAge() {
40 return age;
41 }
42 public void setAge(int age) {
43 this.age = age;
44 }
45 @Override
46 public String toString() {
47 return "Person [name=" + name + ", age=" + age + "]";
48 }
49 public Object clone() throws CloneNotSupportedException {
50 Person person = (Person)super.clone();
51 return person;
52 }
53 }
程序运行结果:
1 false
2 Person [name=张三, age=23]
3 Person [name=张三, age=23]
4
5 Person [name=李四, age=24]
6 Person [name=张三, age=23]
7
8 Person [name=李四, age=24]
9 Person [name=王五, age=25]
2.1假设对象的某些属性特征较复杂:(需要new对象来赋值)
例:情况2.
1 class Person{
2 private String name;
3 private int age;
4 private Company com;
5 }
6
7
8 class Company{
9 private String name;
10 private int age;
11 private String address;
12 }
在情况2下能够采用思路A编程吗?
让我们来试一试:思路A
1 public class Person implements Cloneable{
2
3 public static void main(String[] args) throws CloneNotSupportedException {
4 // 测试
5 //1.创建原型对象
6 Company com = new Company("tencent", 5, "深圳");
7 Person person = new Person("张三", 23, com);
8 //原型克隆
9 Person clonePerson = (Person)person.clone();
10 System.out.println(person == clonePerson);
11 System.out.println(person);
12 System.out.println(clonePerson);
13
14 //2.改变原型对象的com
15 Company personCom = person.getCom();
16 personCom.setName("alibaba");
17 personCom.setAge(3);
18 personCom.setAddress("杭州");
19 System.out.println(person);
20 System.out.println(clonePerson);
21
22 //3.改变克隆对象的com
23 Company clonePersonCom = clonePerson.getCom();
24 clonePersonCom.setName("baidu");
25 clonePersonCom.setAge(4);
26 clonePersonCom.setAddress("beijing");
27 System.out.println(person);
28 System.out.println(clonePerson);
29 }
30
31 private String name;
32 private int age;
33 private Company com;
34
35 public Person() {}
36
37 public Person(String name, int age, Company com) {
38 this.name = name;
39 this.age = age;
40 this.com = com;
41 }
42
43 public String getName() {
44 return name;
45 }
46 public void setName(String name) {
47 this.name = name;
48 }
49 public int getAge() {
50 return age;
51 }
52 public void setAge(int age) {
53 this.age = age;
54 }
55 public Company getCom() {
56 return com;
57 }
58
59 public void setCom(Company com) {
60 this.com = com;
61 }
62
63 @Override
64 public String toString() {
65 return "Person [name=" + name + ", age=" + age + ", com=" + com + "]";
66 }
67 public Object clone() throws CloneNotSupportedException {
68 Person person = (Person)super.clone();
69 return person;
70 }
71 }
1 public class Company implements Cloneable{
2
3 private String name;
4 private int age;
5 private String address;
6 public Company() {
7 }
8 public Company(String name, int age, String address) {
9 this.name = name;
10 this.age = age;
11 this.address = address;
12 }
13 public String getName() {
14 return name;
15 }
16 public void setName(String name) {
17 this.name = name;
18 }
19 public int getAge() {
20 return age;
21 }
22 public void setAge(int age) {
23 this.age = age;
24 }
25 public String getAddress() {
26 return address;
27 }
28 public void setAddress(String address) {
29 this.address = address;
30 }
31
32 @Override
33 public String toString() {
34 return "Company [name=" + name + ", age=" + age + ", address=" + address + "]";
35 }
36 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
4
5 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]]
6 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]]
7
8 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=beijing]]
9 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=beijing]]
这时会发现,已经有错误产生了.
当我们改动person或者clonePerson的com值时,另一个对象的com也会随之发生改变.
修改方法:思路B
①:Person, Company都要实现Cloneable接口.
②:在对Person对象进行克隆的同时也要对Company对象进行克隆.
根据思路B编写程序:
1 public class Person implements Cloneable{
2
3 public static void main(String[] args) throws CloneNotSupportedException {
4 // 测试
5 //1.创建原型对象
6 Company com = new Company("tencent", 5, "深圳");
7 Person person = new Person("张三", 23, com);
8 //原型克隆
9 Person clonePerson = (Person)person.clone();
10 System.out.println(person == clonePerson);
11 System.out.println(person);
12 System.out.println(clonePerson);
13
14 //2.改变原型对象的com
15 Company personCom = person.getCom();
16 personCom.setName("alibaba");
17 personCom.setAge(3);
18 personCom.setAddress("杭州");
19 System.out.println(person);
20 System.out.println(clonePerson);
21
22 //3.改变克隆对象的com
23 Company clonePersonCom = clonePerson.getCom();
24 clonePersonCom.setName("baidu");
25 clonePersonCom.setAge(4);
26 clonePersonCom.setAddress("北京");
27 System.out.println(person);
28 System.out.println(clonePerson);
29 }
30
31 private String name;
32 private int age;
33 private Company com;
34
35 public Person() {}
36
37 public Person(String name, int age, Company com) {
38 this.name = name;
39 this.age = age;
40 this.com = com;
41 }
42
43 public String getName() {
44 return name;
45 }
46 public void setName(String name) {
47 this.name = name;
48 }
49 public int getAge() {
50 return age;
51 }
52 public void setAge(int age) {
53 this.age = age;
54 }
55 public Company getCom() {
56 return com;
57 }
58
59 public void setCom(Company com) {
60 this.com = com;
61 }
62
63 @Override
64 public String toString() {
65 return "Person [name=" + name + ", age=" + age + ", com=" + com + "]";
66 }
67 public Object clone() throws CloneNotSupportedException {
68 Person person = (Person)super.clone();//克隆Person
69 person.setCom((Company)com.clone());//克隆Company
70 return person;
71 }
72 }
1 public class Company implements Cloneable{
2
3 private String name;
4 private int age;
5 private String address;
6 public Company() {
7 }
8 public Company(String name, int age, String address) {
9 this.name = name;
10 this.age = age;
11 this.address = address;
12 }
13 public String getName() {
14 return name;
15 }
16 public void setName(String name) {
17 this.name = name;
18 }
19 public int getAge() {
20 return age;
21 }
22 public void setAge(int age) {
23 this.age = age;
24 }
25 public String getAddress() {
26 return address;
27 }
28 public void setAddress(String address) {
29 this.address = address;
30 }
31
32 public Object clone() throws CloneNotSupportedException{
33 return (Company)super.clone();
34 }
35
36 @Override
37 public String toString() {
38 return "Company [name=" + name + ", age=" + age + ", address=" + address + "]";
39 }
40 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
4
5 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]]
6 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
7
8 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]]
9 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=北京]
根据思路B我们可以得到两个相互独立的对象.
但是,又产生了新的问题:
若是在com中还有类似于Company的对象存在呢(内部还有很多属性和方法)?
若是在Person中也有很多类似于Company的对象存在呢?
若是继续采用思路B,写起来会非常麻烦,并且有可能会遗漏(某个对象也许没有被克隆的情况).
针对产生的新的问题,我们需要重新思考解决方案:思路C
①:Person, Company实现Serializable接口.
②:采用对象流创建Person对象.
根据思路C编写程序:
1 import java.io.ByteArrayInputStream;
2 import java.io.ByteArrayOutputStream;
3 import java.io.IOException;
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.io.Serializable;
7
8
9 public class Person implements Serializable{
10
11 public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
12 // 测试
13 //1.创建原型对象
14 Company com = new Company("tencent", 5, "深圳");
15 Person person = new Person("张三", 23, com);
16 //原型克隆
17 Person copyPerson = person.getCopyPerson();
18 System.out.println(person == copyPerson);
19 System.out.println(person);
20 System.out.println(copyPerson);
21
22 //2.person改变com的值
23 Company personCom = person.getCom();
24 personCom.setName("alibaba");
25 personCom.setAge(5);
26 personCom.setAddress("杭州");
27 System.out.println(person);
28 System.out.println(copyPerson);
29
30 //3.copyPerson改变com的值
31 Company copyPersonCom = copyPerson.getCom();
32 copyPersonCom.setName("baidu");
33 copyPersonCom.setAge(3);
34 copyPersonCom.setAddress("北京");
35 System.out.println(person);
36 System.out.println(copyPerson);
37 }
38
39 private String name;
40 private int age;
41 private Company com;
42
43 public Person() {}
44
45 public Person(String name, int age, Company com) {
46 this.name = name;
47 this.age = age;
48 this.com = com;
49 }
50
51 public String getName() {
52 return name;
53 }
54 public void setName(String name) {
55 this.name = name;
56 }
57 public int getAge() {
58 return age;
59 }
60 public void setAge(int age) {
61 this.age = age;
62 }
63 public Company getCom() {
64 return com;
65 }
66
67 public void setCom(Company com) {
68 this.com = com;
69 }
70
71 @Override
72 public String toString() {
73 return "Person [name=" + name + ", age=" + age + ", com=" + com + "]";
74 }
75
76 public Person getCopyPerson() throws IOException, ClassNotFoundException {
77 // 创建输出流
78 ByteArrayOutputStream bos = new ByteArrayOutputStream();
79 ObjectOutputStream oos = new ObjectOutputStream(bos);
80 oos.writeObject(this);
81
82 // 创建输入流
83 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
84 ObjectInputStream ois = new ObjectInputStream(bis);
85 Object obj = ois.readObject();
86 return (Person)obj;
87 }
88 }
1 import java.io.Serializable;
2
3 public class Company implements Serializable{
4
5 private static final long serialVersionUID = 1L;
6 private String name;
7 private int age;
8 private String address;
9 public Company() {
10 }
11 public Company(String name, int age, String address) {
12 this.name = name;
13 this.age = age;
14 this.address = address;
15 }
16 public String getName() {
17 return name;
18 }
19 public void setName(String name) {
20 this.name = name;
21 }
22 public int getAge() {
23 return age;
24 }
25 public void setAge(int age) {
26 this.age = age;
27 }
28 public String getAddress() {
29 return address;
30 }
31 public void setAddress(String address) {
32 this.address = address;
33 }
34
35 @Override
36 public String toString() {
37 return "Company [name=" + name + ", age=" + age + ", address=" + address + "]";
38 }
39 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
4
5 Person [name=张三, age=23, com=Company [name=alibaba, age=5, address=杭州]]
6 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]]
7
8 Person [name=张三, age=23, com=Company [name=alibaba, age=5, address=杭州]]
9 Person [name=张三, age=23, com=Company [name=baidu, age=3, address=北京]]