2023/04/05 更新: 為了避免本文章散落在不同網站,之後統一由部落格更新,再麻煩從部落格查看~
實作不依賴多個類別,而是依賴介面,並把這些類別實作在此介面
(相關的 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()
}
想請問如果新增 structC 不也是要去改 Work 中的程式碼嗎?
把 Start 中這一塊拉出去,讓 Start 依賴於 cpu 這個介面的好處是什麼呢?
感謝~
ps 錯字:封裝「在」
嗨嗨你好,你可以想成:
PS5{}
CPUFacade
interface相關的實作如果彼此只依賴interface,開工前定義好,小美要改實作就不會影響到小明PS5{}
的使用。
在有多個人員來實作系統時,Facade Pattern切分了人員的耦合,更好體現他的用途,一人實作的時候會比較無感。
恩恩!昨天有再看看其他例子,再看了你的講解有更理解了~謝謝你