一、“組件協作”模式
概述:現代軟件專業分工之后的第一個結果是劃分出了框架和應用。而“組件協作”模式通過晚綁定,來實現框架和應用的松耦合,是兩者之間協作的常用模式。
這個思想的典型模式是:Template模板方法、Strategy策略模式、Observer/Event觀察者模式.
ps:這并非表示其他模式就不注重組件協作的問題,只是這三個模式在這個特性上尤為突出。
二、設計動機
在現在的軟件構建的過程中,常常會有穩定的整體結構,但是各個子模塊常常會有頻繁變化的需求,還有可能在軟件構造中,由于不同模塊的不同構造時間,子模塊代碼晚于整體穩定模塊。
三、模式場景
下面展示一段庫和程序開發中的例子:我在Playground中書寫代碼舉例
//庫發開程序員
class Library{
func step1() -> Void {
//...
}
func step3() -> Void {
//...
}
func step5() -> Void {
//...
}
}
//iOS應用程序開發程序員
class Application{
func step2() -> Bool {
//...
return true
}
func step4() -> Void {
//...
}
}
//邏輯代碼
let lib:Library = Library()
let app:Application = Application()
lib.step1()
if (app.step2()) {
lib.step3()
}
for _ in 0...4 {
app.step4()
}
lib.step5()
這個例子中展示了開發中iOS開發程序員和庫開發程序員的例子。這里假設了庫代碼和程序開發中的方法先后執行順序的問題。
但是這其中埋藏著一個問題,作為庫開發人員,其實調用庫的邏輯代碼流程一般而言應該由庫開發程序員來設定,它應該是穩定的,不應修改的。所以我們可以嘗試來改寫它。
四、修改設計
現在我們來利用模板方法來進行修改,我們將算法代碼中穩定的部分固定在Library里,而將變化的部分留給子類。于是這里Application繼承于Library。
class Library{
func Run(){
func step1() -> Void {
//...
}
func step3() -> Void {
//...
}
func step5() -> Void {
//...
}
step1()
if (step2()) {
step3()
}
for _ in 0...4 {
step4()
}
step5()
}
func step2() -> Bool {
//...
return true
}
func step4() -> Void {
//...
}
}
class Application:Library{
//重載變化的部分
override func step2() -> Bool {
//...
return true
}
override func step4() -> Void {
//...
}
}
//主邏輯
let app:Application = Application()
app.Run()
不得不承認,這個模式看上去十分簡單,這個模式的存在依賴于面向對象的特點,但往往很多人在書寫代碼的時候,雖然使用面向對象語言,但是設計思想往往是結構化的。
如果step1是變化的,你就可以重載step1方法。關鍵是抓住一個算法中變化的部分。假如step1-step5全都是不變化的,那么沒有一個設計模式可以適應這種變化。
設計模式的存在是依賴于穩定點。
換言之,假如step1-step5全都是不變的,那么也不需要設計模式了。
模板方法模式的思想是定義一個穩定的算法骨架,而將變化的部分放置到子類中去。子類可以通過override來重寫變化的部分。這樣達到設計模式復用的目的。
需要注意的是,這個模式的存在依賴run(穩定)的存在,必須有一部分是穩定的,如果run函數出現了變化,這個模式就是失敗的。所以我們必須找出不變的部分。
第一種寫法為早綁定,第二種寫法為晚綁定。
就如上圖所示,一般而言,庫開發往往都早于我們App開發,晚開發的東西調用早開發的東西即為早綁定,這種思想其實十分正常,c語言時期都默認這種做法。
但當有了面向對象特性之后,我們就可以實現晚綁定。
五、模板方法的弊端
模板方法在面向對象語言中使用非常多,但是它也有它自己的弊端。
因為把主要邏輯都封在了父類中,例子中的iOS App開發人員或者說對于繼承父類的子類,只需要重載某些步驟,甚至一句調用代碼都不用寫,應用程序就可以直接跑起來。
但這樣,上層開發人員(此處指實現子類的程序員)就會只知道用法,卻不清楚整個實現邏輯的感覺。因為整個邏輯骨架都封裝在父類中。
所以作為應用程序app開發人員,有時也有必要去了解一下庫的實現。
六、要點總結
1.模板方法是非常簡單基礎的設計模式,幾乎每一個面向對象開發者都使用過。用最簡單的結構,實現代碼復用。
2.需要靈活對待變化點,不要讓"你調用我,而是讓我調用你",理解早綁定和晚綁定。