iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Software Development

什麼都不會還敢說你是 RD 啊?畢業後的後端入職前準備系列 第 28

【Day 28】Design Patterns with Go II:Prototype, Singleton, Facade

今天稍微提一下 design patterns 的分類,
也看看設計模式:Prototype, Singleton, Facade 的 Go 程式碼
ㄚ,Prototype 的 Go 實作細節沒看懂,之後有機會再補吧

  • 程式碼都來自 golang-design-pattern,註解是我自己改的,希望有更好理解一些。
  • Refactoring Guru 的 DESIGN PATTERNS 網頁寫得很不錯,很系統化在介紹一個 pattern 的優缺點 / 如何實作 / 跟其他 pattern 的關係

Design Patterns 的分類

Design patterns 可以分為三大類:Creational / Structural / Behavioral,
雖然看了解釋但感受還沒那麼深,可參考 The Catalog of Design Patterns
其中這幾天,提到的都是 creational 類型的 design patterns,
而今天只有 Facade 是 behavioral。

Prototype(原型模式)

複製已經存在的物件,然後稍微改一點東西。

[Design Pattern] Prototype 原型模式 這邊提到 Prototype Pattern 非常適合用在有深層結構而且高度自定義的物件上面,在這種情況下你通常不會想從頭建立這些物件,另一方面也可以提高程式碼的可讀性。

Go 實作 07_prototype 還沒看很懂,先不放上來了

Singleton(單例模式)

確保一個 class 只能產生一個 instance

可能要存取某個共享的資源,例如資料庫或檔案。

Go 沒有物件,用大寫表示 public 小寫表示 private

import "sync"

type Singleton interface {
	foo()
}

type singleton struct{}

// foo 表示這個 singleton 的 private function
func (s singleton) foo() {}

// 宣告 instance
var (
	instance *singleton
	once     sync.Once
)

// 外部可呼叫 GetInstance 獲得 singleton instance
func GetInstance() Singleton {
	once.Do(func() {
		instance = &singleton{}
	})

	return instance
}

至於其他細節參考 Singleton

Facade(外觀模式)

主要是提供一個 interface 供外界操作,但把內部複雜的子系統隱藏起來

以下面的程式碼來說,若A、B api 有更新異動,則去更改 facade 實作 apiImplTest()
也就是外部 client 依賴於這層 facade interface,而自己不需要知道內部子系統(A、B api)的邏輯。

本來不太理解為什麼要抽出來一層,但後來想想如果是別的程式要用那就很合理呢,如果某個功能背後會用到不同的第三方庫或工具,那寫好一個 facade interface,就能在很多地方實體化這個好懂好用的 facade,而不用每次用到類似功能還需要再理解一次這些複雜的子系統。
可以參考 Facade 中的 VideoConverter 範例

facade interface 宣告與實作

func NewAPI() API {
	return &apiImpl{
		a: NewAModuleAPI(),
		b: NewBModuleAPI(),
	}
}

//API is facade interface of facade package
type API interface {
	Test() string
}

//facade implement
type apiImpl struct {
	a AModuleAPI
	b BModuleAPI
}

func (a *apiImpl) Test() string {
	aRet := a.a.TestA()
	bRet := a.b.TestB()
	return fmt.Sprintf("%s\n%s", aRet, bRet)
}

AModule 宣告與實作

這裏讓 NewAModuleAPI 是大寫,所以其實 client 也可以直接呼叫啦...或許會有這樣的需求?
B 也差不多

// ################################
//NewAModuleAPI return new AModuleAPI
func NewAModuleAPI() AModuleAPI {
	return &aModuleImpl{}
}

//AModuleAPI ...
type AModuleAPI interface {
	TestA() string
}

type aModuleImpl struct{}

func (*aModuleImpl) TestA() string {
	return "A module running"
}

上一篇
【Day 27】Design Patterns with Go I:Simple Factory / Factory / Abstract Factory
下一篇
【Day 29】學 Go 之路的小檢討 + concurrent merge sort
系列文
什麼都不會還敢說你是 RD 啊?畢業後的後端入職前準備31

1 則留言

0
juck30808
iT邦新手 3 級 ‧ 2021-10-14 12:08:04

恭喜即將邁入完賽啦~

我要留言

立即登入留言