一起了解原型模式
原型模式
原型模式,用起來其實就是做clone操作,clone一個對象,越過構造器,在特定使用場景下增加效率。
UML
使用場景:
先說說原型模式主要的淺拷貝和深拷貝:
淺拷貝:
可被clone的對象:
- 實現 Cloneable接口
- 重寫clone方法
- 先clone,再給參數賦值
深拷貝:
對于上面ArrayList,它自身實現類cloneable接口的,所以它本身也是可以clone的,對于對象,賦值后,是指向同一個地址的,對于淺拷貝來說,如果改了list對象,那么原有的對象list也會被修改到。所以對于list對象,我們也需要拷貝一下,修改如下。
public class Document implements Cloneable {private String mText;private ArrayList<String> list = new ArrayList<>();public String getmText() {return mText;}public void setmText(String mText) {this.mText = mText;}@Overrideprotected Document clone() throws CloneNotSupportedException {Document document = (Document) super.clone();document.mText = this.mText;document.list = (ArrayList<String>) this.list.clone();return document;} }復制代碼檢驗
首先:對于淺拷貝
- 我們用下面一段代碼來做檢驗:
- 輸出:
這里很明顯的能看到,我們改了String類型,也改了list對象。但是輸出后,原始的String類型的text沒變,但是list卻被改變了。 這是為什么呢?
原因其實是: String類型是不可變類型,所以我們不推薦在for循環中使用+號來拼接一樣,因為每+一次就會創建一塊內存來裝。同理,這里的雖然拷貝了string類型,但是第二個對象修改的時候,string的text是指向了新的地址而不是把原地址數據給改了,所以原對象的text并沒被改。但list就不一樣了,改的是原對象地址的數據 所以我們才會需要深拷貝。
然后我們再檢驗一次深拷貝的:
輸出內容:
內容原始:Document{mText='11111100000', list=[00]} 內容修改:Document{mText='111111', list=[00, 111]} 內容原始:Document{mText='11111100000', list=[00]}復制代碼我們使用深拷貝的時候,將對象list也clone了,就沒有指向的不再是原有地址了,所以改動也就影響不到原來數據咯。
另外:實現Cloneable接口只是一種方式。要實現clone也不一定非要實現這個接口(使用Object來重寫clone方法的話一定要實現,不然會拋出異常)。
如果使用new的方式并不耗資源等,clone的時候我們傳入自己,用new的效率或許會更高:
public Document(Document document) {this.mText = document.getmText();this.list = document.getList();}@Overridepublic Document clone() throws CloneNotSupportedException {Document document = new Document(this);return document;} 復制代碼總結:原型模式在copy資源非常方便,當然拷貝不一定比new快,所以需要評估測試再考慮是否不用new
轉載于:https://juejin.im/post/5b9893f9f265da0aa528f351
總結
- 上一篇: python Tags 母板 组
- 下一篇: 梦到别人生了个女儿是什么意思