# 前言
這次是系列的第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)的差異
不過單純要模擬原型模式的話,並不太需要在乎這兩者的差別
但實作到真實場合的時候就要考慮細一點了
而且深淺複製也會因為程式語言的不同,會有些許的差異