必知必會(huì)的22種設(shè)計(jì)模式(GO語(yǔ)言)

日常工作中免不了使用設(shè)計(jì)模式崎场,那么你使用了哪些設(shè)計(jì)模式呢?

設(shè)計(jì)模式是什么干厚?

設(shè)計(jì)模式是一種在軟件設(shè)計(jì)中對(duì)常見(jiàn)問(wèn)題的通用解決方案螃宙。

它們是經(jīng)過(guò)驗(yàn)證的、可重用的設(shè)計(jì)思想挂捅,可以幫助解決開(kāi)發(fā)過(guò)程中遇到的各種問(wèn)題堂湖。

設(shè)計(jì)模式提供了一種共同的詞匯表和方法論状土,讓不同團(tuán)隊(duì)的開(kāi)發(fā)人員能夠更有效地溝通和協(xié)作蒙谓,從而提高軟件的穩(wěn)定性退盯、可靠性和可維護(hù)性。

整體來(lái)看慰照,設(shè)計(jì)模式包含了如下 22 種琉朽,主要分為三大類

  1. 創(chuàng)造型
  2. 結(jié)構(gòu)型
  3. 行為型

[圖片上傳失敗...(image-ca8a5e-1697122452141)]

看上去很多種,實(shí)際上咱們實(shí)際仔細(xì)去看每種模式的思想和細(xì)節(jié)的時(shí)候墅垮,能夠發(fā)現(xiàn)其實(shí)我們?nèi)粘9ぷ髦杏杏玫礁皇遣恢涝瓉?lái)是應(yīng)用了設(shè)計(jì)模式

有道無(wú)術(shù)術(shù)可求,有術(shù)無(wú)道止于術(shù) 灾梦,那么先來(lái)學(xué)習(xí)學(xué)習(xí)每種設(shè)計(jì)模式的思想妓笙,以及 GO 語(yǔ)言實(shí)現(xiàn)的 demo

創(chuàng)建型模式

1. 工廠模式

工廠模式 解決了在不指定具體類的情況下創(chuàng)建產(chǎn)品對(duì)象的問(wèn)題

案例:

寫一個(gè)工廠,可以生產(chǎn)車萧福,目前這個(gè)工廠可以生產(chǎn) bmw 和 benz 辈赋,那么我們需要獲取一輛車的時(shí)候,就直接去車廠拿車即可

2. 抽象工廠模式

它能創(chuàng)建一系列相關(guān)的對(duì)象悟民, 而無(wú)需指定其具體類

案例:

一個(gè)大賣場(chǎng)焕蹄,有衣服腻脏,有 鞋子,有 NB 品牌永品,有 Nike 品牌,此時(shí)我們就可以使用抽象工廠钾麸,抽象衣服炕桨,鞋子,每一個(gè)品牌自行去實(shí)現(xiàn)具體的衣服和鞋子

3. 生成器模式

能夠分步驟創(chuàng)建復(fù)雜對(duì)象

案例:

建一座建筑钥平,無(wú)論你是冰室姊途,還是住房,是非常復(fù)雜的立叛,我們演示簡(jiǎn)化為 4 個(gè)步驟贡茅,每個(gè)步驟都會(huì)創(chuàng)建新的對(duì)象,大體會(huì)經(jīng)歷如下步驟

  • 搭建框架
  • 裝修
  • 安裝門
  • 安裝床

4. 原型模式

能夠復(fù)制已有對(duì)象彤叉, 而又無(wú)需使代碼依賴它們所屬的類

案例:

此時(shí)可以想到我們的程序目錄村怪,和目錄下的文件,是否可以通過(guò)這種方式實(shí)現(xiàn)呢柬焕?

程序的目錄和文件梭域,能夠滿足遞歸的結(jié)構(gòu),目錄和文件富玷,都是同樣的結(jié)構(gòu)

5. 單例模式

能夠保證一個(gè)類只有一個(gè)實(shí)例, 并提供一個(gè)訪問(wèn)該實(shí)例的全局節(jié)點(diǎn)

單例實(shí)例會(huì)在結(jié)構(gòu)體首次初始化時(shí)創(chuàng)建雀鹃,若多個(gè)協(xié)程創(chuàng)建励两,如何保證協(xié)程安全呢?

package main

import (
   "fmt"
   "sync"
)

var lock sync.Mutex

var one sync.Once

type Single struct {
}

// 此時(shí)創(chuàng)建的  SingleInstance 默認(rèn)為 零值傅瞻, 也就是 nil
var SingleInstance *Single

// getOneInstance 顯示使用 鎖的方式盲憎,保證線程安全
func getOneInstance() *Single {
   if SingleInstance == nil {
      // 此處可能會(huì)有多個(gè)協(xié)程進(jìn)來(lái)
      lock.Lock()
      defer lock.Unlock()
      // 此處再繼續(xù) 判斷 SingleInstance 是否為 nil,是因?yàn)榭赡芷渌麉f(xié)程已經(jīng)拿到鎖掸读,且初始化好了 SingleInstance 后宏多,當(dāng)前協(xié)程才拿到鎖
      if SingleInstance == nil {
         fmt.Println("getOneInstance: Create SingleInstance successfully ...")
         SingleInstance = &Single{}
      } else {
         fmt.Println("1 getOneInstance: SingleInstance has been created ...")
      }
   }else {
      fmt.Println("2 getOneInstance: SingleInstance has been created ...")
   }
   return SingleInstance
}

// getTwoInstance 使用 sync.Once 達(dá)到同樣的效果
func getTwoInstance() *Single {
   if SingleInstance == nil {
      fmt.Println("getTwoInstance: in SingleInstance == nil ...")
      one.Do(func() {
         // 因此 one.Do 只會(huì)執(zhí)行一次,因此不會(huì)出現(xiàn)  getOneInstance 的情況肾请,因此此處無(wú)需判斷 SingleInstance 是否為 nil
         fmt.Println("getTwoInstance: Create SingleInstance successfully ...")
         SingleInstance = &Single{}
      })
   } else {
      fmt.Println("getTwoInstance: SingleInstance has been created ...")
   }
   return SingleInstance
}

func main() {

   for i := 0; i < 20; i++ {
      //getOneInstance()
      getTwoInstance()
   }

   fmt.Scanln()// 輸出回車就會(huì)結(jié)束

}
5_single_instance>go run main.go
getTwoInstance: in SingleInstance == nil ...
getTwoInstance: Create SingleInstance successfully ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...
getTwoInstance: SingleInstance has been created ...

結(jié)構(gòu)型模式

6. 適配器模式

讓接口不兼容的對(duì)象能夠相互合作

案例:

可能我們都用過(guò)生活中的適配器吧铛铁,我們手機(jī)是 Type C 的接口却妨,電腦是 USB 的接口,那么這個(gè)時(shí)候倍权,如何讓 TypeC 的接口和 USB 的接口連接上呢捞烟?這個(gè)時(shí)候就可以使用適配器來(lái)處理

7. 橋接模式

可將一個(gè)大類或一系列緊密相關(guān)的類拆分為抽象和實(shí)現(xiàn)兩個(gè)獨(dú)立的層次結(jié)構(gòu), 從而能在開(kāi)發(fā)時(shí)分別使用 案例:

不同的顯示器要接入計(jì)算機(jī)默辨,那么計(jì)算機(jī)可以獨(dú)立開(kāi)發(fā)苍息,顯示器也可以獨(dú)立開(kāi)發(fā)壹置,無(wú)論計(jì)算機(jī)里面有 windows 的蒸绩,還是 mac 的 仍然支持設(shè)置 顯示器

  • demo 7

8. 組合模式

使用它將對(duì)象組合成樹狀結(jié)構(gòu)铃肯, 并且能像使用獨(dú)立對(duì)象一樣使用它們

案例:

咱們的目錄樹中有 目錄押逼,有 文件, 目錄可以進(jìn)行查詢挑格,文件也是可以進(jìn)行查詢沾歪,將他們組合起來(lái),他們各自仍然是獨(dú)立的對(duì)象

9. 代理模式

能夠提供對(duì)象的替代品或其占位符

案例:

對(duì)于 nginx 反向代理很熟悉吧挫望,咱們手?jǐn)]一個(gè)簡(jiǎn)單的反向代理磁椒,運(yùn)用代理模式

10. 裝飾器模式

允許你通過(guò)將對(duì)象放入包含行為的特殊封裝對(duì)象中來(lái)為原對(duì)象綁定新的行為

案例:

年輕人喜歡喝奶茶泉哈,不同的口味不同的配置有不同的價(jià)格,喝奶茶丛晦,有原味的,有加珍珠的匹层,有加椰果的斧吐,有加奶的 ,各有各的價(jià)格

那么 奶茶 和 珍珠煤率,椰果,奶 是相互獨(dú)立的洋只,各自是一個(gè)獨(dú)立的對(duì)象 我們可以在珍珠對(duì)象中,放入奶茶對(duì)象肢扯,進(jìn)而達(dá)到 奶茶中加珍珠担锤,加椰果,加奶 達(dá)到不同的價(jià)格

11. 外觀模式

能為程序庫(kù)铭腕、 框架或其他復(fù)雜類提供一個(gè)簡(jiǎn)單的接口

案例:

咱們?nèi)ャy行存錢多糠,取錢,表面上看著很簡(jiǎn)單夹孔,一進(jìn)一出即可,殊不知銀行后面的內(nèi)部系統(tǒng)之間復(fù)雜的交互只怎,我們簡(jiǎn)化一下 例如 銀行后面涉及到 賬戶系統(tǒng)怜俐,檢測(cè)系統(tǒng),數(shù)據(jù)庫(kù)系統(tǒng)盾沫,通知系統(tǒng) 這個(gè)時(shí)候 就可以使用 外觀模式殿漠,對(duì)于客戶端來(lái)說(shuō)使用非常簡(jiǎn)單,無(wú)需關(guān)注其內(nèi)部復(fù)雜系統(tǒng)

12. 享元模式

通過(guò)共享多個(gè)對(duì)象所共有的相同狀態(tài)

案例:

設(shè)計(jì)一個(gè)足球比賽游戲蕾哟,A 隊(duì)隊(duì)服是 紅色莲蜘,B 隊(duì)隊(duì)服是 藍(lán)色,且整個(gè)隊(duì)伍就只有一個(gè)套衣服 逐哈,此處就應(yīng)用了享元模式

如果不應(yīng)用享元模式,那么我們每一個(gè)人都要 new 一套衣服昂秃,咱確實(shí)沒(méi)有必要這樣做

行為模式

13. 命令模式

將請(qǐng)求轉(zhuǎn)換為一個(gè)包含與請(qǐng)求相關(guān)的所有信息的獨(dú)立對(duì)象

案例:

咱們以插件的方式來(lái)注入到程序中,如 我們平日看電視肠骆,需要按按鈕,按鈕上有各種按鍵嘴瓤,例如開(kāi)機(jī)鍵莉钙,關(guān)機(jī)鍵

另外,這個(gè)按鍵又是對(duì)于哪些設(shè)備生效呢?此處咱們是對(duì) TV 生效刻获,可以使用命令模式,很好的插入這些相關(guān)對(duì)象

14. 策略模式

讓你定義一系列算法蝎毡, 并將每種算法分別放入獨(dú)立的類中, 以使算法的對(duì)象能夠相互替換

案例:

咱們知道緩存的處理方式别垮,有 FIFO扎谎,LFU,LRU胧奔, 那么當(dāng)我們將數(shù)據(jù)載入緩存的時(shí)候预吆,使用的算法進(jìn)行切換了,我們?nèi)匀恍枰@個(gè)緩存是可以正常處理的拐叉,這個(gè)時(shí)候,咱們就可以使用策略模式

又如我們需要取到一個(gè)目的地宿礁,我們可以坐飛機(jī)蔬芥,可以乘高鐵红且,也可以走路去涤姊,在過(guò)程中仍然可以隨意切換交通方式,最終壁酬,我們都是抵達(dá)目的地恨课,沒(méi)有問(wèn)題,同樣也可以使用策略模式

15. 模板模式

在超類中定義一個(gè)算法的框架希俩, 允許子類在不修改結(jié)構(gòu)的情況下重寫算法的特定步驟

案例:

模板的方式纲辽,相信我們平日用的也非常多,舉個(gè)例子我們就能夠很好的感受到

我們要獲取消息拖吼,保存消息到緩存,生成消息回復(fù)篙议,發(fā)送消息怠硼,這幾個(gè)步驟不變的情況下,我們可以使用 微信吩愧,可以使用企業(yè)微信增显,自然也是可以使用飛書來(lái)處理

我們生成 源 msg,期望放到緩存中同云,生成具體的回復(fù)信息,將消息發(fā)送出去 對(duì)于這種步驟固定星澳,但是對(duì)于每一步驟期望有自己的實(shí)現(xiàn)方式的旱易,期望去重寫具體的實(shí)現(xiàn)方式的腿堤,可以使用模板方法

獲取到信息之后笆檀,wechat ,wework酗洒,lark 有不同的處理方式枷遂,但是他們的整體處理結(jié)構(gòu)是一樣的

16. 迭代器模式

讓你能在不暴露集合底層表現(xiàn)形式 (列表、 棧和樹等) 的情況下遍歷集合中所有的元素

案例:

我們提供出去的接口矩桂,不期望別人能看到我們自身的數(shù)據(jù)結(jié)構(gòu)痪伦,我們就可以使用迭代器的方式來(lái)進(jìn)行處理,可以隱藏實(shí)際的數(shù)據(jù)結(jié)構(gòu)

17. 觀察者模式

允許你定義一種訂閱機(jī)制, 可在對(duì)象事件發(fā)生時(shí)通知多個(gè) “觀察” 該對(duì)象的其他對(duì)象

案例:

這種設(shè)計(jì)模式應(yīng)用很多笆制,我們舉例一個(gè)食堂吃飯的例子

多個(gè)員工觀察食堂,食堂做好菜之后 訂閱的員工都能夠收到通知在辆,員工便傾巢而出

18. 責(zé)任鏈模式

允許你將請(qǐng)求沿著處理者鏈進(jìn)行發(fā)送证薇。 收到請(qǐng)求后浑度, 每個(gè)處理者均可對(duì)請(qǐng)求進(jìn)行處理鸦概, 或?qū)⑵鋫鬟f給鏈上的下個(gè)處理者

案例:

例如處理一件事情,有一個(gè)固定的流程先慷,正如一個(gè)新員工入職

員工入職可以看做是一個(gè)責(zé)任鏈咨察, 前臺(tái)報(bào)道,人事制度宣講摄狱,合同部合同簽訂无午,送入具體部門 , 這種部門職責(zé)明確宪迟,鏈路清晰踊跟,可以使用 責(zé)任鏈模式,允許你將請(qǐng)求沿著處理者鏈進(jìn)行發(fā)送 對(duì)于新員工來(lái)說(shuō)商玫,只需要知道去去找前臺(tái)報(bào)道即可

19. 備忘錄模式

允許在不暴露對(duì)象實(shí)現(xiàn)細(xì)節(jié)的情況下保存和恢復(fù)對(duì)象之前的狀態(tài)。

案例: 例如某白領(lǐng)使用備忘錄袭异,記錄了 1 炬藤,2 ,3 條信息上真,然后想調(diào)出 2 快照來(lái)進(jìn)行查看

20. 中介者模式

能讓你減少對(duì)象之間混亂無(wú)序的依賴關(guān)系羹膳。 該模式會(huì)限制對(duì)象之間的直接交互, 迫使它們通過(guò)一個(gè)中介者對(duì)象進(jìn)行合作陵像。

案例:

醫(yī)院里面有很多不同職業(yè)的人來(lái)看病,如何保證用戶進(jìn)入醫(yī)生辦公室發(fā)生沖突呢妻怎?

這個(gè)時(shí)候就有一個(gè)醫(yī)院服務(wù)人員來(lái)進(jìn)行管理泞歉,負(fù)責(zé)和不同的職業(yè)的病人溝通, 雖然病人之間沒(méi)有溝通偿洁,但是他們依然能有有序的進(jìn)入到醫(yī)生辦公室內(nèi)看病沟优,此時(shí)醫(yī)院服務(wù)人員就是一個(gè)中介者

21. 狀態(tài)模式

讓你能在一個(gè)對(duì)象的內(nèi)部狀態(tài)變化時(shí)改變其行為, 使其看上去就像改變了自身所屬的類一樣

案例:

售賣機(jī)暫時(shí)只售賣一種從產(chǎn)品挠阁,有 4 種狀態(tài)溯饵,沒(méi)貨丰刊,有貨增拥,正在請(qǐng)求商品,已投幣

對(duì)于不同的狀態(tài)秩仆,應(yīng)對(duì)不同的動(dòng)作

22. 訪問(wèn)者模式

將算法與其所作用的對(duì)象隔離開(kāi)來(lái)

案例:

目前有 3 種結(jié)構(gòu), Dog澄耍,Cat晌缘,Monkey 都實(shí)現(xiàn)了 IAnimal interface,訪問(wèn)者有 AreaVs(計(jì)算面積)选酗,VolumeVs(計(jì)算體積),ColorVs (計(jì)算顏色) 都實(shí)現(xiàn)了 IVisitor interface

以后如果需要類似于增加計(jì)算體脂率的岳枷,那么就可以加一個(gè) visitor 即可,且對(duì)其他的訪問(wèn)者和結(jié)構(gòu)沒(méi)有影響

如果需要增加結(jié)構(gòu)氢烘,例如增加 pig 家厌,那么直接去實(shí)現(xiàn) Animal 即可椎工,對(duì)其他的結(jié)構(gòu)和訪問(wèn)者沒(méi)有影響

有沒(méi)有覺(jué)得很巧妙呢?

歡迎點(diǎn)贊维蒙,關(guān)注,收藏

朋友們殖熟,你的支持和鼓勵(lì)斑响,是我堅(jiān)持分享钳榨,提高質(zhì)量的動(dòng)力

[圖片上傳失敗...(image-d67a3e-1697122452141)]

好了纽门,本次就到這里

技術(shù)是開(kāi)放的,我們的心態(tài)饼齿,更應(yīng)是開(kāi)放的蝙搔。擁抱變化,向陽(yáng)而生杂瘸,努力向前行。

我是阿兵云原生敌土,歡迎點(diǎn)贊關(guān)注收藏运翼,下次見(jiàn)~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矩欠,隨后出現(xiàn)的幾起案子悠夯,更是在濱河造成了極大的恐慌,老刑警劉巖沦补,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夕膀,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡产舞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門耻煤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嘴办,你說(shuō)我怎么就攤上這事买鸽。” “怎么了眼五?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵看幼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我诵姜,道長(zhǎng),這世上最難降的妖魔是什么暇赤? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任宵凌,我火速辦了婚禮,結(jié)果婚禮上溜腐,老公的妹妹穿的比我還像新娘。我一直安慰自己挺益,他們只是感情好乘寒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著黍檩,像睡著了一般始锚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瞧捌,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天姐呐,我揣著相機(jī)與錄音,去河邊找鬼曙砂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸠澈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播际度,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼涵妥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窒所?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤墩新,失蹤者是張志新(化名)和其女友劉穎窟坐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體臣疑,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡徙菠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缺狠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萍摊。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖穷劈,靈堂內(nèi)的尸體忽然破棺而出笼恰,到底是詐尸還是另有隱情社证,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布追葡,位于F島的核電站奕短,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏崖飘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一朱浴、第九天 我趴在偏房一處隱蔽的房頂上張望达椰。 院中可真熱鬧,春花似錦啰劲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至藕甩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狭莱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工默怨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辉阶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓垃僚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親谆棺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容