原型模式(Prototype):該模式的思想就是將一個對象作為原型,對其進行復制、克隆,產生一個和原對象類似的新對象。而這里的復制有兩種:淺復制、深復制。
**淺復制**:將一個對象復制后,基本數據類型的變量都會重新創建,而引用類型,指向的還是原對象所指向的。
**深復制**:將一個對象復制后,不論是基本數據類型還有引用類型,都是重新創建的。簡單來說,就是深復制進行了完全徹底的復制,而淺復制不徹底。
下面通過示例進行說明:
##一、淺復制
### 1、uml建模:

### 2、代碼實現
~~~
/**
* 原型模式:將一個對象作為原型,對其進行復制、克隆,產生一個和原對象類似的【新對象】。
*
* 而這里的復制有兩種:淺復制、深復制
*
* 示例(一) 淺復制:將一個對象復制后,基本數據類型的變量都會重新創建,
*
* 而引用類型,指向的還是原對象所指向的,【不會重新創建】。
*/
class Prototype implements Cloneable {
private int age;
private int[] array = new int[] { 1, 2, 3 };
public Prototype() {
}
public Prototype(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
/**
* 因為Cloneable接口是個空接口
*
* 此處的重點是super.clone()這句話,super.clone()調用的是Object的clone()方法,而在Object類中,clone()是native的
*
* 這就涉及到JNI,關于JNI還有NDK以后會講到,這里你只要記住淺復制的核心是super.clone()。
*/
public Object cloneObject() throws CloneNotSupportedException {
Prototype prototype = (Prototype) super.clone();
return prototype;
}
}
/**
* 客戶端測試類
*
* @author Leo
*/
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Prototype prototype = new Prototype(20);
Prototype cloneProto = (Prototype) prototype.cloneObject();
/**
* 通過打印可以看到:prototype和cloneProto這兩個同一類型的變量指向的是兩個不同的內存地址
*
* 這說明克隆成功
*/
System.out.println("prototype = " + prototype);
System.out.println("cloneProto = " + cloneProto);
/**
* 要完全復制一個對象的話,那么它的引用類型變量array指向的肯定是不同的內存地址
*
* 而這里的引用類型變量array,指向的還是原對象所指向的。可以看到打印的內存地址是相同的。
*
* 這說明對象復制不徹底
*/
System.out.println("prototype.getArray() = " + prototype.getArray());
System.out.println("cloneProto.getArray() = " + cloneProto.getArray());
/**
* 透過這個例子可以看到:淺復制并沒有將對象進行完全復制
*/
}
}
~~~
##二、深復制
### 1、uml建模:

### 2、代碼實現
~~~
/**
* 示例(二) 深復制:將一個對象復制后,不論是基本數據類型還有引用類型,都是【重新創建】的。
*
* 簡單來說,就是深復制進行了完全徹底的復制,而淺復制不徹底。
*
* 由于這里涉及到對對象的讀寫,所以這里用到了對象的序列化--實現了Serializable接口
*/
class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private int age;
private int[] array = new int[] { 1, 2, 3 };
public Prototype() {
}
public Prototype(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
/* 深復制 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 寫入當前對象的二進制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 讀出二進制流產生的新對象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
/**
* 客戶端測試類
*
* @author Leo
*/
public class Test {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
Prototype prototype = new Prototype(20);
Prototype cloneProto = (Prototype) prototype.deepClone();
/**
* 通過打印可以看到:prototype和cloneProto這兩個同一類型的變量指向的是兩個不同的內存地址
*
* 這說明克隆成功
*/
System.out.println("prototype = " + prototype);
System.out.println("cloneProto = " + cloneProto);
/**
* 通過打印可以看到,兩個對象的引用類型變量array指向的是不同的內存地址
*
* 這說明對象進行了完全徹底的復制
*/
System.out.println("prototype.getArray() = " + prototype.getArray());
System.out.println("cloneProto.getArray() = " + cloneProto.getArray());
/**
* 當然我們也可以試著打印一下引用變量的內容,
*
* 可以看到:內容是不變的(1 2 3),改變的只是引用變量指向的內存地址。
*/
int[] proArray = prototype.getArray();
int[] cloneProtoArray = cloneProto.getArray();
for (int p : proArray) {
System.out.print(p + "\t");
}
System.out.println();
for (int p : cloneProtoArray) {
System.out.print(p + "\t");
}
}
}
~~~
##三、總結
1、淺復制的核心是super.clone(),它調用的是Object的clone()方法,而在Object類中,clone()是native的。
2、要實現深復制,需要采用二進制流的形式寫入當前對象,再對其進行讀取。
- 前言
- (一)策略模式建模與實現
- (二)觀察者模式建模與實現
- (三)裝飾者模式建模與實現
- (四)工廠方法模式建模與實現
- (五)抽象工廠模式建模與實現
- (六)單例模式建模與實現
- (七)命令模式建模與實現
- (八)適配器模式建模與實現
- (九)外觀模式建模與實現
- (十)模板方法模式建模與實現
- (十一)迭代器模式建模與實現
- (十二)組合模式建模與實現
- (十三)狀態模式建模與實現
- (十四)代理模式建模與實現
- (十五)建造者模式建模與實現
- (十六)原型模式建模與實現
- (十七)橋接模式建模與實現
- (十八)責任鏈模式建模與實現
- (十九)備忘錄模式建模與實現
- (二十)解釋器模式建模與實現
- (二十一)享元模式建模與實現
- (二十二)中介者模式建模與實現
- (二十三)訪問者模式建模與實現
- Java設計模式博客全目錄