原型模式:(復制對象)
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=北京]]