開發中總是說的“鉤子”是什麼?

說起“鉤子(Hook)”這個名詞,可能身為開發的同學大都聽說過。所謂Hook機制,是從Windows編程中流行開的一種技術。其主要思想是提前在可能增加功能的地方埋好(預設)一個鉤子,這個鉤子並沒有實際的意義,當我們需要重新修改或者增加這個地方的邏輯的時候,把擴展的類或者方法掛載到這個點即可。

這可能不太好理解,接下來就開始以PHP為例講述下鉤子到底是什麼。

講到“鉤子”,一定要提前說明的是一種設計模式,那就是行為型設計模式中的模板方法模式,明白了它的話,會讓我們更容易理解鉤子。

什麼是模板方法模式

模板方法模式是一種基於繼承的代碼複用,它是一種類行為型模式,在其結構中只存在父類與子類之間的繼承關係。通過使用模板方法模式,可以將一些複雜流程的實現步驟封裝在一系列基本方法中,在抽象父類中提供一個稱之為模板方法的方法來定義這些基本方法的執行次序,而通過其子類來實現某些步驟,從而使得相同的算法框架可以有不同的執行結果。

簡單而言,這個模式更像是進行婚禮活動(父類),按照某一個安排的流程進行,只是每個不同的婚禮(子類)來說,雖然流程是一樣的,但是每個流程中,每個婚禮都有自己的玩法,例如結婚都要接親,都要被伴娘攔住玩遊戲,玩的是什麼可能都不一樣,然後接回家以後要進行一些禮節,可能有的遞茶,有的吃餃子什麼的各不相同,以代碼的形式說明如下

開發中總是說的“鉤子”是什麼?

開發中總是說的“鉤子”是什麼?

要注意的是,在處理的過程中,要遵循反向控制接口(“好萊塢原則”),這個原則是指父類調用子類的操作,而子類不調用父類的操作。好萊塢原則於模版方法設計模式緊密相關,因為它在父類中實現,除了templateMethod方法外,父類的其他方法都是抽象和受保護的方法。所以,儘管客戶實例化一個具體類,但是它調用了父類中實現的方法。

什麼時候使用模板方法

如果已經明確算法中的一些步驟,不過這些步驟可以採用多種不同的方法進行實現,就可以使用模板方法模式。如果算法的步驟不變,可以把這些步驟交給子類去實現。這種情況下,可以使用設計模式來組織抽象類中的基本操作,然後子類去做這些基本操作所需要的具體過程。

還有一種用法可能稍微複雜一些,可能需要把子類共同的行為放在一個類裡面,以避免代碼重複,畢竟每次實現的子類不回是完全不同的,估計很快就會產生重複代碼。

最後一點,就是可以使用模板方法模式來控制子類拓展,也就是我們本次需要說的鉤子。可以利用鉤子控制拓展,只在鉤子操作所在的某些位置允許拓展。

模板方法設計模式中的鉤子

有的時候,模板方法函數中可能有一個不想要的步驟,例如,在我們購買商品的時候要計算最終價格,商品價格+運費+服務產生費用,不過在有些活動中,顧客商品價格滿100元就可以免運費。這裡就要使用到模板方法的鉤子。

也就是說,在模板方法設計模式中,利用鉤子可以將一個方法作為模板方法的一部分,不過不一定會用到這個方法。換句話說,它是方法的一部分,不過它包含一個鉤子,可以處理例外的情況,子類可以為算法增加一個可選元素,這樣以來,儘管仍然按照父類模板方法建立的順序執行,但是有可能並不完全按照模板方法期望的那樣動作。

不過這可能有點違背之前說的需要遵守的“好萊塢原則”,因為子類沒有遵循父類設置的順序,好萊塢原則要求只有父類能夠改變框架。鉤子的話更像一個“後門”,進行處理例外的情況。

舉個鉤子的簡單的例子,就拿免運費的例子進行實現。注意,雖然子類可以改變鉤子的行為,但是仍然要遵守模板方法中定義的執行順序。

開發中總是說的“鉤子”是什麼?

抽象類IHook定義了幾個抽象方法,並且確定了他們的執行順序,這裡hook方法放到了中間,實際上它可以放在順序中的任意位置。$special代表的是是否免運費。

開發中總是說的“鉤子”是什麼?

addTax()和cost()都是標準方法,只有一個實現,不過addShippingHook()的實現有所不同,其中有一個條件來確定是否要增加運費,這個就是鉤子。 客戶 Client類具體使用不做說明了。其實就是一個設置和調用了。

優缺點

優點

1.提高代碼複用性 ,將相同部分的代碼放在抽象的父類中

2.提高了拓展性 ,將不同的代碼放入不同的子類中,通過對子類的擴展增加新的行為

3.實現了反向控制,通過一個父類調用其子類的操作,通過對子類的擴展增加新的行為,實現了反向控制 & 符合“開閉原則”

缺點

引入了抽象類,每一個不同的實現都需要一個子類來實現,導致類的個數增加,從而增加了系統實現的複雜度。

你理解中的“鉤子”是什麼樣的呢?

鏈接:https://www.jianshu.com/p/60c9a09d1ac3


分享到:


相關文章: