原型模式指定的是用原型實例指定創建對象的種類,並用拷貝這些原型來創建新的對象。某些對象可以從頭創建,而其他對象可以創建爲現有對象的複製項並進行修改,但是使用
這些對象的系統或流程不會根據它們的實際創建方式區分它們。在相似的方式下,在使用“原型”模式時,客戶系統應獨立於它使用的對象的創建、合成和表示等詳細信息。
原型適用性:
1.當一個系統應該獨立於它的產品創建、構成和表示時。 2.當要實例化的類是在運行時刻指定時,例如,通過動態裝載。 3.爲了避免創建一個與產品類層次平行的工廠類層次時。 4.當一個類的實例只能有幾個不同狀態組合中的一種時。 建立相應數目的原型並克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。
在java中有淺複製和深複製,淺複製是使用內置java.lang.Object的clone()方法來實現;深複製是覆蓋Clone方法來實現。
淺複製:如果是基本數據類型,就會全部複製,若是引用對象則僅僅複製對象的引用,而不復制他所引用的對象。所以改變了其中一個對象的地址,會影響到另一個對象。
package com.yu.jian;
/**
* 被引用的對象
* @author maojycom
*
*/
public class User{
private String userName;
public User() {
super();
}
public User(String userName) {
super();
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
package com.yu.jian;
/**
* @author maojycom
*
*/
public class People implements Cloneable{
private String name;
private User user;
public People() {
super();
}
public People(String name) {
this.name = name;
this.user = new User(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
/**
* 覆蓋父類的clone方法
*/
@Override
protected Object clone(){
try {
//淺複製:調用父類的clone方法
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
package com.yu.jian;
/**
* java淺複製和深複製測試
* @author Administrator
*
*/
public class Test {
public static void main(String[] args) {
People p = new People("www");
//複製一份People出來
People p1 = (People) p.clone();
//false 對象的引用類型不同
System.out.println(p == p1);
//true 對象的class相同
System.out.println(p.getClass() == p1.getClass());
//原始對象改變了name屬性
p.setName("ggg");
//複製對象name屬性沒有改變
System.out.println(p1.getName());
//對people中的引用對象user改變其屬性
p.getUser().setUserName("aaa");
//複製對象中的username屬性改變了
System.out.println(p1.getUser().getUserName());
}
}
輸出:falsetrue
www
aaa
深複製:把要複製的對象所引用的對象都複製了一遍。是把引用的對象動態分配的內存也一併複製過來,對象和它所引用的對象一起復制。
User類和Test類沒有改變,只是改變了People中的clone方法。
package com.yu.jian;
/**
* @author maojycom
*
*/
public class People implements Cloneable{
private String name;
private User user;
public People() {
super();
}
public People(String name) {
this.name = name;
this.user = new User(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
/**
* 覆蓋父類的clone方法
*/
@Override
protected Object clone(){
//深複製:複製該類的一個新對象,使其與原始對象相互獨立。
People cloneObj = new People("maojy");
return cloneObj;
}
}
輸出:false
true
maojy
maojy
還有序列化複製和延遲複製就不寫了,瞭解就行。
如果複製的對象都是基本類型,就用淺複製;如果複製的對象有引用類型,且對象引用的地址不會經常改變,就用淺複製,若經常需要改變,就用深複製。