您可於此 design_pattern repo 下載 Design Pattern 系列程式碼。
前言
這次的 Pattern 讓我想到以前做過的一個 App,但當時還沒有學習到 Pattern,所以沒有用 Pattern 來處理,現在發現這個功能很適合套用 prototype pattern
這是一個用來編輯音樂燈光秀的 App,有興趣的讀者可以下載玩玩看 🙂
需求
今天收到了客人的需求,客人反應編輯完一條燈光還要編輯另外六條好浪費時間,能不能新增 Copy & Paste 的功能,加快編輯以節省時間,如下圖
物件導向分析 (OOA)
理解需求後,讓我們來快速實作物件導向分析吧!
當我們需要複製 LightShowData
時,只需要同樣的 jsonObject 資料重新 new 一個 LightShowData
即可複製一份
察覺 Forces
來看看上面這樣的設計會有哪些問題
- 如果我們的 constructor 很複雜,參數非常多,那麼重新 new 一個實體會需要知道很多細節。
- 如果 constructor 創建實體的過程,是很耗時複雜的計算,重新 new 一個實體會讓創建過程效率變差。
套用 Prototype Pattern ( Solution ) 得到新的 Context ( Resulting Context )
做完 OOA,察覺 Forces,看清楚整個 Context 後,就可以來套用 Prototype Pattern 解決這個問題
先來看一下 Prototype Pattern 的 UML
原型模式主要包含以下兩個角色:
-
Prototype(原型):這是一個抽象介面,定義了複製自身的方法。在實體實現中,這個介面可以是一個抽象類或者實體類,主要目的是提供一個複製自己的方法。這使得在不需要知道物件實體類別的情況下也能創建物件的副本。
-
Concrete Prototype(實體原型):實現或繼承自原型介面的類。這個類實現了在原型介面中定義的複製(clone)方法,用於創建自身的一個精確副本。在實體實現時,這個類需要提供一個方法來複製自身的屬性,確保新創建的物件與原有物件在狀態上是相同的,但在記憶體中是獨立的。
我們來將 LightShow App 套用 Prototype Pattern
如此我們就得到了一個全新的 Resulting Context
物件導向程式設計 (OOP)
再來我們就可以開始進行物件導向程式開發
[LightShowDataPrototype]
interface LightShowDataPrototype {
val startIndex: Int
val lightDataList: List<Int>
fun clone(): LightShowDataPrototype
}
[LightShowData]
package prototypepattern.source
class LightShowData: LightShowDataPrototype {
override val startIndex: Int
override val lightDataList: List<Int>
constructor(originalDataList: List<Int>) {
startIndex = originalDataList[0]
lightDataList = originalDataList.subList(1, originalDataList.size).map { it * 2 }
}
constructor(startIndex: Int, lightDataList: List<Int>) {
this.startIndex = startIndex
this.lightDataList = lightDataList
}
override fun clone(): LightShowDataPrototype {
return LightShowData(startIndex, lightDataList.toList())
}
}
[main]
fun main() {
val originalData = listOf(1, 2, 3, 4, 5)
// Before using prototype pattern
val originalLightShowData: LightShowDataPrototype = LightShowData(originalData)
val newLightShowData: LightShowDataPrototype = LightShowData(originalData)
println(originalLightShowData)
println(newLightShowData)
// After using prototype pattern
val clonedLightShowData: LightShowDataPrototype = LightShowData(originalData)
println(originalLightShowData)
println(clonedLightShowData)
}
我們可以發現,透過 clone() 方法複製,就可以不重複執行下面的程式碼,提升程式碼效能了
originalDataList.subList(1, originalDataList.size).map { it * 2 }
Leave a comment