設計模式中常用的幾個“套路”

    Gof的設計模式一共有23種模型,這23種模型只能算是一些情景下的通用解法,是離散的而非系統的解決方案,所以在理解、記憶和應用時,如果不是花費足夠的時間熟悉和使用這些模型,就難以準確地使用合適的模型或者模型的變體解決開發中的問題。不過還好,這個23種模型中,存在着更加底層的常用套路,能夠被提取出來,可以幫助理解和掌握設計模式的精髓。

接口

    接口,毫無疑問是設計模式中最常用的技巧。接口是java中的概念,一般相當於C++中無屬性的抽象類。在23中設計模式中大部分都使用了接口,唯一不同的地方是,不同設計模式使用接口的原因可能並不一樣。
    接口可以用來作爲一種標準規範。在現實中比較類似的例子是工業生產中對於零件的標準,這種一般都會有國家規範。比如一個汽車生產過程中需要某種特定大小的齒輪,但是又絲毫不關心齒輪的生產工藝、材料成分等這種比較細節的實現,這時候只需要從供應商那裏買回和設計稿中一樣規格的齒輪,汽車能夠跑起來即可。如果在使用中發現這種齒輪不好用或者不經濟實惠,就可以直接替換另外一種同樣規格的齒輪。因爲有了齒輪的標準規範,才能使這種替換順利進行。接口在各種模型中就可以作爲一種標準規範。比如在策略模式中,可以爲不同的策略定義同一個接口,這樣在使用不同策略時,可以做到隨時替換。在狀態模式中,可以爲不同的狀態定義同一接口,這樣是使用狀態類的實例時,可以隨時替換不同的狀態。在命令模式中,可以爲不同的命令定義同一接口,這樣在觸發命令的邏輯中,不用關心具體命令的類型,可以根據場景替換不同的命令。
    接口的另一個作用是可以用來屏蔽系統的細節。在進行模塊設計時,如果暴露過多細節給外部,外部可以使用系統內部具體的類或者任何參數,會使系統和外部耦合增大。如果系統內部邏輯需要更改,比如替換類、修改參數等情況,相應的系統外部也需要修改,這往往會造成不必要的麻煩。接口這時候就可以用來作爲屏蔽系統內外的守衛,這種應用最典型的外觀模式,抽象工廠模式也是比較類似的套路。對外提供的接口方法,作爲內部給外部開放的入口,內部任何邏輯的改變,product的搭配和組裝的變化,都不會影響外部系統。另外一個比較特殊的使用是備忘錄模式。備忘錄模式中爲備忘錄定義一個窄接口,這樣在外部(備忘錄管理者,caretaker)就不能訪問備忘錄的內部數據。而在內部(原發器,originator)定義備忘錄爲內部類,這樣就形成了寬接口,可以訪問備忘錄內部的數據,從而實現了”外緊內松“的模式。

抽象類

    相對於接口,抽象類在設計模式中發揮的作用就不那麼明顯。抽象類和接口的主要區別在於,抽象類中可以定義屬性,可以實現方法的邏輯,這一概念在java和C++中的定義基本是一致的。由於特性的不同,實際上抽象類能夠產生不能夠被接口取代的作用。
    抽象類的延遲實現被使用在了工廠方法和模板方法模式中。一般來說,在構建功能和調用流程都比較相似的類時,如果這些類具有一些相同的邏輯,但是在某些流程又存在不同的邏輯實現,就可以使用抽象類的延遲實現,這在一些框架的搭建上應用廣泛,比如spring mvc。在工廠方法中,抽象類(父類)的方法中定義了一部分構建的流程,同時調用了抽象方法作爲作爲模板方法,返回具體的產品。在子類中實現了模板方法,構建了具體的產品。這樣既複用父類中通用的代碼邏輯,同時也可以使用不同子類區分出不同的產品,充分應用了抽象類延遲實現的特性。模板方法中也使用了抽象類延遲實現的這一特性。在父類中定義一個算法的骨架,將一些步驟延遲到子類中,這樣模板方法模式可以使得子類不改變一個算法的結構,即可以重定義該算法的某些特定步驟。
    抽象類的另一個作用是可以實現子類對原有方法邏輯的拓展。在裝飾模式中,子類裝飾器在運行自己的方法邏輯之前,會使用super.operation方法,先獲得父類方法運行之後的結果,然後再運行自己定義的operation方法的邏輯,這樣可以實現對父類方法的邏輯的擴充疊加甚至是修改。Windows的MFC框架,窗口類往往具有比較複雜的繼承結構,比如一個按鈕類CButton也屬於窗口類。這樣子類在定義自己的代碼時,爲了兼容父類的邏輯,往往需要先調用父類的方法,然後在父類的方法運行結果的基礎上進行拓展。

組合

    組合在設計模式中使用也比較廣泛。相比於繼承,在類中持有某個對象,從而複用某個類對象的能力,這樣會有更好的拓展性。
    組合最常用的功能是代理委託,實現某種形式的解耦。說到代理委託,最典型的非代理模式莫數。在代理模式中,代理類和被代理類需要有一樣的方法定義,在內部持有一個被代理類的對象的引用。構建代理類對象需要傳入被代理類的對象,當調用代理類的方法時,代理類實際會在內部調用被調用類的方法。實現代理之後,可以做的事情非常多,比如可以在不修改原有的被代理類的基礎上,對原有被代理類的方法邏輯進行拓展,可以通過代理類和被代理類的聯合實現數據的懶加載,可以屏蔽被代理類的細節,實現與外部系統解耦。這種特性也被應用到了其他的設計模式模型中,比如適配器模式通過代理,將被適配的類和系統的規範進行了統一,算是一個解耦的反向應用。比如迭代器模式,通過組合,訪問數據結構內部,實現了對不同數據結構遍歷的適配,從而使遍歷操作和具體數據結構進行解耦。比如命令模式使用代理,將命令執行方和命令調用方進行解耦。還有中介者模式、訪問者模式、解釋器模式、備忘錄模式中,都可以看到這種功能應用的影子。

    Gof的設計模式中提到的23種設計模式可能只算是應對不同場景的離散模型,而不是系統閉合的完備論證,這中間需要探索的東西還有很多,值得更廣泛的思考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章