設計模式-模板方法模式(Go語言描述)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

這篇文章我們還是繼續我們的設計模式系列, 今天我們帶來的一個全新的設計模式在實際開發中大家肯定都遇到過, 可能大家只是不知道它叫模板方法模式而已, 今天我們就來詳細的說一下什麼是模板方法模式,已經該模式如何運用.

至於什麼是模板方法模式, 我們還是老規矩, 先來個定義, 然後上張類圖更加直觀的看一下.

定義

模板方法模式定義了一個演算法的步驟,並允許子類別為一個或多個步驟提供其實踐方式。讓子類別在不改變演算法架構的情況下,重新定義演算法中的某些步驟.

這個定義還是非常不錯的, 至少認真讀2遍還是可以理解什麼意思的, 而且我們腦袋裡可以想象到該如何設計這樣的一個結構. 那它有什麼樣的使用情境呢? 其實在定義中已經說的很明白了, 大致有一下兩點應用情境:

  1. 某些類別的演算法中,實做了相同的方法,造成代碼的重複.
  2. 控制子類別必須遵守的一些事項

上面兩點總結起來說, 可以這樣認為:

系統的組件都是按照一定的流程執行, 並且不同的組件的實現方式不同,需要我們延遲到子類來實現.

模板方法模式的關鍵點還是在將具體操作延遲到子類實現. 接下來, 我們再來看看類圖, 從類圖中我們可以更見直觀的體會一下模板方法模式.

代碼展示

按照慣例, 在這個環節中我們就應該用go語言來實現模板方法模式了, 不過由於go語言的特殊性, 它並沒有實際意義上的繼承, 所以在go中去實現, 還是和我們上面所說的有點不那麼相同, 所以我決定這裡我們先來用java實現一下模板方法模式, 有了瞭解之後, 我們再來考慮如何用go去實現.在今天這個例子中, 我們打算類比一下男女生在出門的時候不同行為, 男生在出門之前可能就是在睡覺, 睡醒了爬起來就出去了; 而女生不一樣了, 女生是要打扮一番才能出門的.

java版的模板方法模式

在有了上面的實際例子後, 我們就先來用java類比一下. 首先我們需要定義一個介面, 用來規範這個行為.

interface IPerson {    void beforeOut();    void out();}

有了介面, 就必須有實現, 不管男生還是女生, 他都是人, 而且在我們這個情景下, 出門這個行為是一樣的, 不一樣的只是出門之前的行為. 對應到代碼中就是out方法是男女生相同的, 不同的實現是beforeOut方法, 所以我們在設計人這個類的時候之關心out方法的實現.

abstract class Person implements IPerson {    private String name;    public Person(String name) {        this.name = name;    }    public void out() {        beforeOut();        System.out.println("go out...")    }}

這裡我們實現了out方法, 並在 out列印之前調用了beforeOut方法, 至於這個方法如何?, 這裡要看是男生還是女生了, 很簡單, 直接來看代碼.

class Boy extends Person {    public Boy(String name) {        super(name);    }    public void beforeOut() {        System.out.println("get up...")    }}class Girl extends Person {    public Boy(String name) {        super(name);    }    public void beforeOut() {        System.out.println("dress up...")    }}

ok, 不管是男生還是女生, 都繼承自Person這個抽象類別, 並且實現了beforeOut這個方法, 只不過男生的這個方法實現是一個get up, 而女生是一個dress up.

現在,一個簡單的模板方法模式的應用我們就完成了, 從代碼中我們也可以發現, 其實這個模式是很簡單的, 在之前的部落格中我就說過, 設計模式本身都很簡單, 不太容易的是設計模式的應用和實踐.

好了, 在通過java代碼瞭解模板方法模式之後, 下面開始進入今天的重點了, 如何用go去實現呢?

golang版模板方法模式

對golang瞭解的同學都知道, 其實golang並沒有嚴格意義上的繼承機制, 它僅僅是利用組合的特性來類比繼承, 在這方法對於組合優於繼承體現的還是很好的, 不過這也帶來了一些問題, 比如不能實現抽象方法, 上面的方法延遲實現等等. 說到這裡大家不要著急, 雖然golang沒有這個特性, 但是我們完全可以換一種思路來完成它, 畢竟模式是死的, 代碼是活的, 那用什麼方式實現呢? 答案就是綁定! 至於如何運用, 我不多說, 我們直接來看代碼就行了!

根據上面的java代碼, 我們來一一的實現它, 首先是介面, 在golang中我們也有介面, 所以, 我們可以設計一個如下的介面.

type IPerson interface {    SetName(name string)    BeforeOut()    Out()}

這個介面和上面java版的大致相同, 主要的方法都在裡面的, 接下來我們還是要設計一個Person結構體. 這個Person和上面的Person可能不太一樣, 我們先來看代碼.

type Person struct {    Specific IPerson    name     string}

是有點不一樣, 這裡多了一個IPerson類型的欄位, 這個欄位是幹嘛的? 我們上面提過到, 這裡我們準備用綁定的方式來實現模板方法模式, 這裡的這個特殊的欄位其實就是我們要綁定的執行個體, 在我們這個例子中就是男生或者女生了, 到這裡可能很多人要迷惑了, 沒關係, 最後我們在看使用的代碼時就明白了, 這裡我們還是先來看看這個Person有什麼方法吧.

func (this *Person) SetName(name string) {    this.name = name}func (this *Person) Out() {    this.BeforeOut()    fmt.Println(this.name + " go out...")}func (this *Person) BeforeOut() {    if this.Specific == nil {        return    }    this.Specific.BeforeOut()}

第一個方法我們直接無視它, 第二個方法的實現和java版的其實是一樣的, 來看看第三個方法, 這個方法是java版Person沒有去實現的, 按道理將這個BeforeOut是要延遲到子類去實現的, 這個不符合國際慣例啊? 我們還是來看看這個方法的內容吧, 其實關鍵點就一句話, this.Specific.BeforeOut(), 這句話直接調用了我們上面說的那個綁定的執行個體的BeforeOut方法, 仔細品味一下, 還是符合慣例的, 這裡我們只不過用了一種折中的方式來實現方法的延遲實現.

好了, 最難理解的地方我們詳細說了, 下面就是男生和女生的各自實現了, 很簡單, 直接上代碼.

type Boy struct {    Person}func (_ *Boy) BeforeOut() {    fmt.Println("get up..")}type Girl struct {    Person}func (_ *Girl) BeforeOut() {    fmt.Println("dress up..")}

代碼中,不管是Boy還是Girl都匿名組合了Person結構體, 他們的BeforeOut方法的實現也和上面java版的大體相同, 這裡我們就不再多說了, 最後我們來看看這樣一個設計, 我們該如何使用.

func main() {    var p *Person = &Person{}    p.Specific = &Boy{}    p.SetName("qibin")    p.Out()    p.Specific = &Girl{}    p.SetName("loader")    p.Out()}

這裡代碼的主體還是Person, 只不過我們在區分男女生的時候, 給他指定了Specific欄位, 再來回想一下Person結構體的BeforeOut方法的實現, 是不是瞬間就明白怎麼回事了. 最後我們再來看看運行結果.

最後還是關於文章的執行個體代碼的事, 代碼我都放github上了, 歡迎各種star, https://github.com/qibin0506/go-designpattern

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.