软件构造:防御式拷贝(Defensive Copying)
?????????不變量(Invariant)是ADT的一個(gè)重要屬性,它可以保持程序的正確性,幫助發(fā)現(xiàn)錯(cuò)誤??勺償?shù)據(jù)類型(Mutable type)可能對(duì)ADT的不變性帶來影響,防御式拷貝的目的是為了消除可變數(shù)據(jù)類型帶來的表示泄露。
? ? ? ? 表示泄露可能發(fā)生在任何以可變數(shù)據(jù)類型為參數(shù)或返回值的方法中,主要發(fā)生在Constructor和Observer方法中。
???????當(dāng)Constructor方法需要傳入可變參數(shù)時(shí),客戶端對(duì)可變參數(shù)的修改會(huì)導(dǎo)致表示泄露;
? ? ? ?案例分析:
? ? ? ?如下圖,Tweet的屬性timestamp和傳入的參數(shù)timestamp指向同一個(gè)date對(duì)象,當(dāng)客戶端對(duì)傳入?yún)?shù)使用timestamp.setHours()方法時(shí),Tweet內(nèi)部屬性發(fā)生改變;
? ? ?解決方法:
? ? ? ?特別地當(dāng)Collection類型元素已知的時(shí)候(如List),可以使用List.of方法生成不可變的List;
????????當(dāng)Observer方法需要返回可變類型時(shí),客戶端對(duì)可變類型的引用可能導(dǎo)致表示泄露;
?????????????????????????????????????????????????????????????
? ? 常見解決方法:
? ? ? ? 1)當(dāng)返回類型為Date時(shí),返回new Date(olddate.getTime());
? ? ????????????????? ?
? ? ? ? 2)當(dāng)返回類型為L(zhǎng)ist,Set,Map時(shí),以ArrayList為例,可以返回new ArrayList<>(oldlist);?
??????????????????????????????????????
? ? ? ? ? 或者使用Collection類提供的unmodifiableList方法,即Collection.unmodifiableList(oldlist)返回不可修改的包裝類。Set,Map同理;
?* 3)當(dāng)返回類型為自定義可變類型時(shí),這里以實(shí)驗(yàn)一中的可變Person類為例,定義如下:
public class Person {
? ? private final String name;
? ? private final ArrayList<Person> friend;
?
? ? public Person(String name)
? ? {
? ? ? ? this.name = name;
? ? ? ? friend = new ArrayList<>();
? ? }
}
? ? ? ? ? 關(guān)鍵思想是overload一個(gè)新的構(gòu)造方法,以Person類為參數(shù),在構(gòu)造方法中對(duì)所有可變數(shù)據(jù)類型進(jìn)行防御式拷貝,之后每當(dāng)需要返回Person類時(shí),就通過new一個(gè)Person進(jìn)行防御式拷貝;
? ? public Person(Person person)
? ? {
? ? ? ? this.name = person.name;
? ? ? ? this.friend = new ArrayList<>(person.getFriend());
? ? }
? ? ? ? ?也可以進(jìn)一步定義靜態(tài)方法copy()對(duì)防御式拷貝進(jìn)行封裝;
? ? ? 實(shí)例:
總結(jié):
????????防御式拷貝是對(duì)可變數(shù)據(jù)類型缺點(diǎn)的彌補(bǔ),是ADT設(shè)計(jì)過程中不可或缺的組成部分,確保了程序的正確性和健壯性。
總結(jié)
以上是生活随笔為你收集整理的软件构造:防御式拷贝(Defensive Copying)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 郑州泓晟龙腾计算机有限公司,龙腾资料管理
- 下一篇: CodeForces 1278 B.A