iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Software Development

Hey! Go Design Patterns系列 第 23

DAY 23:Facade Pattern,由統一的入口介面來做事

什麼是 Facade Pattern?

實作不依賴多個類別,而是依賴介面,並把這些類別實作在此介面

問題情境

(相關的 code 在Github - go-design-patterns)

當 PS5 啟動時,會用到許多 CPU 相關的指令集,以下方範例來說即是StrcutA{}StrcutB{},如果未來要更改StrcutA{}StrcutB{}DoAction()function 呼叫方式,或者StrcutA{}被棄用要改用StructC{},都必須要修改PS5{}.Start()的實作。

package main

import "fmt"

type StructA struct{}

func (s StructA) DoAction() {}

type StructB struct{}

func (s StructB) DoAction() {}

type PS5 struct {
}

func (p PS5) Start() {
	strcutA := StructA{}
	strcutB := StructB{}
	strcutA.DoAction()
	strcutB.DoAction()
	fmt.Println("start ps5...done!")
}

func main() {
	ps5 := PS5{}
	ps5.Start()
}

我們需要一個方式,能讓做這些更改時PS5{}.Start()不需要修改。

解決方式

PS5{}.Start()可以只依賴特定介面CPUFacade interface 的Work(),所以可以將StrcutA{}StructB{}的使用方式都封裝在Work()中,就算後續StrcutA{}StructB{}有變更呼叫方式或是棄用,都不影響PS5{}.Start()的呼叫。

package main

import "fmt"

type CPUFacade interface {
	Work()
}

type StructA struct{}

func (s StructA) DoAction() {}

type StructB struct{}

func (s StructB) DoAction() {}

type CPU struct{}

func (c CPU) Work() {
	strcutA := StructA{}
	strcutB := StructB{}
	strcutA.DoAction()
	strcutB.DoAction()
}

type PS5 struct {
	cpu CPUFacade
}

func (p PS5) Start() {
	p.cpu.Work()
	fmt.Println("start ps5...done!")
}

func main() {
	ps5 := PS5{cpu: CPU{}}
	ps5.Start()
}

上一篇
DAY 22:Decorator Pattern,巧妙的在方法上增加新功能
下一篇
DAY 24:Composite Pattern,管理有層次的物件們
系列文
Hey! Go Design Patterns30

1 則留言

1
yichin
iT邦新手 5 級 ‧ 2021-10-13 17:57:51

想請問如果新增 structC 不也是要去改 Work 中的程式碼嗎?
把 Start 中這一塊拉出去,讓 Start 依賴於 cpu 這個介面的好處是什麼呢?
感謝~

ps 錯字:封裝「在」

嗨嗨你好,你可以想成:

  • RD小明使用PS5{}
  • RD小美設計CPUFacadeinterface相關的實作

如果彼此只依賴interface,開工前定義好,小美要改實作就不會影響到小明PS5{}的使用。


在有多個人員來實作系統時,Facade Pattern切分了人員的耦合,更好體現他的用途,一人實作的時候會比較無感。

yichin iT邦新手 5 級 ‧ 2021-10-14 15:38:23 檢舉

恩恩!昨天有再看看其他例子,再看了你的講解有更理解了~謝謝你

我要留言

立即登入留言