# 前言 這次是系列的第12篇 主題是原型模式(Prototype Pattern) # 原型模式 一種創建型設計模式,它允許通過複製現有的物件來創建新物件,而不是通過實例化來生成物件。 這種模式適用於創建成本高昂或代價大的物件,通過複製來提升性能或簡化物件創建過程。 原型模式的核心思想是:利用已有物件作為模板進行複製,快速創建新物件。 結構: - 原型接口(Prototype Interface): 定義一個方法,用於複製自身(通常稱為 clone 方法)。 - 具體原型(Concrete Prototype): 實現原型接口,提供對自身的深複製或淺複製功能。 - 客戶端(Client): 通過調用原型的 clone 方法來創建新的物件,而不是直接調用構造函數。 這次的情境是我們想要幾台電腦 但與以往不同,這次我們直接複製 接著上程式 ```python= from abc import ABC, abstractmethod import copy class Prototype(ABC): @abstractmethod def duplicate(self): pass class Computer(Prototype): def __init__(self, cpu: str, gpu: str, disks: list[str]) -> None: self.cpu = cpu self.gpu = gpu self.disks = disks def __str__(self) -> str: return f"Computer(cpu={self.cpu}, gpu={self.gpu}, disks={self.disks})" def duplicate(self): return copy.copy(self) def deep_clone(self): return copy.deepcopy(self) if __name__ == '__main__': pc = Computer(cpu='i7-12700', gpu='RTX-3070ti', disks=['MX500', 'P5 Plus']) shallow_copy = pc.duplicate() deep_copy = pc.deep_clone() print(pc) print(shallow_copy) print(deep_copy) print(id(pc.disks)) print(id(shallow_copy.disks)) print(id(deep_copy.disks)) pc.disks.append("T705") print(pc) print(shallow_copy) print(deep_copy) ``` 輸出的結果為 ``` Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus']) Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus']) Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus']) 1838815236416 1838815236416 1838817599872 Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus', 'T705']) Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus', 'T705']) Computer(cpu=i7-12700, gpu=RTX-3070ti, disks=['MX500', 'P5 Plus']) ``` 好的,看起來很完美👍 # 淺複製與深複製 根據[Python官方文件](https://docs.python.org/zh-tw/3/library/copy.html) ``` 淺層複製建構一個新的複合物件,然後(在儘可能的範圍內)將原始物件中找到的物件的參照插入其中。 深層複製建構一個新的複合物件,然後遞迴地將在原始物件裡找到的物件的副本插入其中。 ``` 簡單來說,在Python中 無論是淺複製還是深複製 都會建立一個新的物件,差別在於 淺複製中的子物件會是原始物件的參考(reference) 而深複製會是原始物件的的副本 所以上面程式碼中的這個部分 ```python= print(id(pc.disks)) print(id(shallow_copy.disks)) print(id(deep_copy.disks)) ``` `shallow_copy.disks`跟`pc.disks`會指向相同的記憶體位址 而`deep_copy.disks`因為深複製的關係,則會指向不同的記憶體位址 但值得注意的是 在此範例中,`Computer.disks`是個`list`,是可變(mutable)的 如果今天`print`出來的是字串(string)或整數(interger)等不可變(immutable)的物件 那輸出的結果會指向相同的記憶體位址 假設上面程式碼的最後,我們增加了下面的原始碼 ```python= print(id(pc.cpu)) print(id(shallow_copy.cpu)) print(id(deep_copy.cpu)) ``` 則輸出的結果為 ``` 1819848730544 1819848730544 1819848730544 ``` 可以看到都是指向一樣的記憶體位址 # 心得 實作挺簡單的 值得注意的是淺拷貝(shallow copy)與深拷貝(deep copy)的差異 不過單純要模擬原型模式的話,並不太需要在乎這兩者的差別 但實作到真實場合的時候就要考慮細一點了 而且深淺複製也會因為程式語言的不同,會有些許的差異