個人網(wǎng)站做電影網(wǎng)站南京seo排名優(yōu)化公司
原型設(shè)計模式
- 一 .簡介
- 二. 案例
- 三. 補(bǔ)充知識
前言
這是我在這個網(wǎng)站整理的筆記,有錯誤的地方請指出,關(guān)注我,接下來還會持續(xù)更新。
作者:神的孩子都在歌唱
一 .簡介
原型模式提供了一種機(jī)制,可以將原始對象復(fù)制到新對象,然后根據(jù)我們的需要進(jìn)行修改。原型設(shè)計模式使用java克隆來復(fù)制對象。
原型模式的克隆分為淺克隆和深克隆。
深拷貝(Deep Copy)和淺拷貝(Shallow Copy)是指在進(jìn)行對象復(fù)制時所產(chǎn)生的兩種不同結(jié)果。
深拷貝:創(chuàng)建一個新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原有屬性所指向的對象的內(nèi)存地址。
淺拷貝:創(chuàng)建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。
Java中的Object類中提供了 clone()
方法來實(shí)現(xiàn)淺克隆。 Cloneable 接口是上面的類圖中的抽象原型類,而實(shí)現(xiàn)了Cloneable接口的子實(shí)現(xiàn)類就是具體的原型類。
二. 案例
通過一個例子就很容易理解原型設(shè)計模式。假設(shè)我們有一個從數(shù)據(jù)庫加載數(shù)據(jù)的對象。現(xiàn)在我們需要在程序中多次修改這些數(shù)據(jù),因此使用通過new 一個新的對象,并再次從數(shù)據(jù)庫加載所有數(shù)據(jù)并不是一個好主意。更好的方法是將現(xiàn)有對象克隆到新對象中,然后進(jìn)行數(shù)據(jù)操作。原型設(shè)計模式其實(shí)就是需要你確保正在拷貝的對象應(yīng)該提供拷貝功能。它不應(yīng)該由任何其他類完成。然而,是否使用對象屬性的淺拷貝或 深拷貝 取決于 需求及其設(shè)計決策。
以下是代碼案例:
這里我定義了一個籃球類,通過重新實(shí)現(xiàn)clone方法來實(shí)現(xiàn)深拷貝
/*** @author chenyunzhi*/
public class Ball implements Cloneable{private final List<String> ballList;public Ball(){ballList = new ArrayList<>();}public Ball(List<String> ballList){this.ballList=ballList;}/*** 模擬從數(shù)據(jù)庫中拿數(shù)據(jù)*/public void loadData(){ballList.add("basketball");ballList.add("soccer");}public List<String> getBallList() {return ballList;}@Overridepublic Ball clone() throws CloneNotSupportedException {return new Ball(new ArrayList<>(this.getBallList()));}}
然后我寫了一個測試類方便測試,這里我new了一個 ball 對象,然后對ball對象進(jìn)行拷貝,對拷貝的對象進(jìn)行了增添和刪除他們相互之間都不影響
/*** @author chenyunzhi*/
public class PrototypePatternTest {public static void main(String[] args) throws CloneNotSupportedException {Ball ball = new Ball();ball.loadData();Ball ballNew =ball.clone();Ball ballNew1 = ball.clone();List<String> list = ballNew.getBallList();list.add("tennis");List<String> list1 = ballNew1.getBallList();list1.remove("basketball");// 輸入修改后的球類列表System.out.println("ball List: "+ball.getBallList());System.out.println("ballNew List: "+list);System.out.println("ballNew1 List: "+list1);System.out.println("ball List: "+ball.getBallList());}}
測試結(jié)果
結(jié)論:如果沒有提供對象克隆,我們每次都必須調(diào)用數(shù)據(jù)庫來獲取球類列表。然后進(jìn)行那些耗費(fèi)資源和時間的操作。這就是java中原型設(shè)計模式的全部內(nèi)容。
三. 補(bǔ)充知識
問題: 為什么淺拷貝中 拷貝的對象修改了某個String類型的值,被拷貝對象的值沒有變化?
在Java類庫中,所有基本類型的包裝類都是不可變類,例如Integer、Float等。
不可變類(Immutable Class) 在初始化后的所有信息不能被修改。而更改String成員的值相當(dāng)于在堆中新建一個String引用,舊的String常量引用仍然存在于堆中,只不過還沒回收,從而讓兩個引用不相等。這時你以為String是被克隆,但造成其不相等的原因其實(shí)是賦值。
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
轉(zhuǎn)載說明:務(wù)必注明來源,附帶本人博客連接。