原型模式(Prototype Pattern)
通過複製已有的對象來創建新的對象,其中「已有的對象」被稱為「原型」。
- 優點:對調用組件而言,調用組件不需要了解創建對象的過程需要使用到什麼「Class」或者「Struct」,也不用了解創建過程中的細節。
使用這個模式也可以避免每次重複創建對象所需要消耗的時間。
將一個「值類型」賦值給變量時,Swift會自動使用「原型模式」。值類型是使用結構體定義的,而且所有Swift內置的類型的底層都是使用結構體實現的。
也就是說我們可以複製字符串、布爾值、集合、枚舉、元祖和數值類型,只需要將他們賦值給變量即可完成複製。
舉一個例子,我們先來創建ValueTypeShop
1 2 3 4 5 6 7 8 |
struct ValueTypeShop { var name:String var place:String func printDetails() { print("\(name) is at \(place)") } } |
我們通過struct ValueTypeShop來創建一個shopA
1 |
let valueTypeShopA = ValueTypeShop(name: "Shop A", place: "West") |
接著直接複製一個valuetypeShopA,並且修改內容。
1 2 3 |
var valueTypeShopB = valueTypeShopA valueTypeShopB.name = "Shop B" valueTypeShopB.place = "West" |
我們試試看把兩個對象print出來
1 2 |
valueTypeShopA.printDetails() valueTypeShopB.printDetails() |
從結果可以看到,我們順利地創造出了兩個對象,並且在建立valueTypeShopB的時候,並沒有執行到「初始化」的動作,而是複製了valueTypeShopB。
1 2 |
Shop A is at West Shop B is at West |
然而如果我們複製的是引用類型,就會發生衝突了。
1 2 3 4 5 6 7 8 9 10 11 12 |
class ReferenceTypeShop { var name:String var place:String init(name:String, place:String) { self.name = name self.place = place } func printDetails() { print("\(name) is at \(place)") } } |
main.swift
1 2 3 4 5 6 7 8 |
let referenceShopC = ReferenceTypeShop(name: "Shop C", place: "West") let referenceShopD = referenceShopC referenceShopD.name = "Shop C" referenceShopD.place = "West" referenceShopC.printDetails() referenceShopD.printDetails() |
這裡可以看到,雖然我們只有修改一個對象,但是兩邊都變了
1 2 |
Shop C is at West Shop C is at West |
這裡用兩張圖來示意複製「值類型」和複製「引用類型」的情況:
- 僅複製指針又稱為淺複製(Shallow Copy)
- 複製對象本身又稱為深複製(Deep Copy)
延伸思考:NSCopying協議。
上面提到的「原型模式的例子」放在github上提供參考。