意圖 原型模式是創建型設計模式,可以複製已存在的對象而無需依賴它的類。 問題 假如現在有一個對象,我們想完全複製一份新的,我們該如何做? 1. 創建同一個類的新對象 2. 遍歷所有已存在對象的值,然後將他們的值複製到新對象。 很好,但是我們會發現存在如下問題: 1. 該對象的值並不一定全對對外開放, ...
意圖
原型模式是創建型設計模式,可以複製已存在的對象而無需依賴它的類。
問題
假如現在有一個對象,我們想完全複製一份新的,我們該如何做?
- 創建同一個類的新對象
- 遍歷所有已存在對象的值,然後將他們的值複製到新對象。
很好,但是我們會發現存在如下問題:
- 該對象的值並不一定全對對外開放,比如Java中的private,外部無法訪問。
- 使用這種辦法必須知道該對象所屬的類而且依賴這個類。
- 有些時候我們只知道該對象實現的介面,而不是具體的實現類。
解決
這個時候我們就需要原型模式。原型模式將克隆過程委托給被克隆的對象。該模式為所有支持克隆的對象聲明一個公共介面,這個介面允許克隆一個對象,而不必將代碼和該對象的類耦合。通常,這樣的介面只包含一個克隆方法。
克隆方法的實現在所有類中都非常相似。該方法創建當前類的一個對象,並將舊對象的所有欄位值轉移到新對象中。這樣就可以複製私有欄位,因為大多數編程語言都允許對象訪問屬於同一類的私有欄位。
結構
原型模式包含如下角色
- Prototype:它是聲明克隆方法的介面,是所有具體原型類的公共父類,可以是抽象類也可以是介面,甚至還可以是具體實現類。
- ConcretePrototype:它實現在抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象
實例
在Java中,所有的類都繼承了java.lang.Object。Object提供了clone方法能實現Java對象複製。
我們只需註意兩點即可。
- 實現克隆的Java類必須實現一個標識介面Cloneable,表示這個Java類支持被覆制。如果沒有實現這個介面但調用了clone()方法,Java編譯器將拋出一個CloneNotSupportedException異常。
- 淺克隆和深克隆
java的clone函數只是“淺克隆”,也就是僅對變數值做複製。如果是引用變數,其內容指向的記憶體地址是不變的。
參考文獻
https://refactoring.guru/design-patterns/prototype