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