Facade Design Pattern
门面(外观)模式(Facade Design Pattern)是一种结构型设计模式。意图隐藏底层系统的复杂性,并为客户端提供一个简单易用的操作界面。
它为系统中许多底层接口提供了统一的接口,因此从客户端的角度来看,减少了需要操作的系统元素数量,它更易于使用。
业务架构设计层次划分时,BFF(Backend For Frontend)层便是对该模式很好的应用。
UML Diagram
- Internal Subsystem x 为底层系统,各自拥有一套操作接口(doX(),doY(),doZ());
- Facade 为外观层,持有多个 Subsystem 实例,并公开更简洁的操作接口 doSomething();
Example
Question:
整合一下服务接口,以服务 A 的 DoSomething 接口对外提供服务:
- Sub1 服务的 DoX()
- Sub2 服务的 DoY()
- Sub3 服务的 DoZ()
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package main
import "fmt"
type AFacade struct {
bSvc *SubSvc1
cSvc *SubSvc2
dSvc *SubSvc3
}
func NewAFacde() *AFacade {
return &AFacade{
bSvc: &SubSvc1{},
cSvc: &SubSvc2{},
dSvc: &SubSvc3{},
}
}
func (a *AFacade) DoSomething() {
fmt.Println("Start all tasks......")
a.bSvc.DoX()
a.cSvc.DoY()
a.dSvc.DoZ()
fmt.Println("Completed all tasks")
}
type SubSvc1 struct{}
func (svc *SubSvc1) DoX() {
fmt.Println("Completed task X by SubSvc1")
}
type SubSvc2 struct{}
func (svc *SubSvc2) DoY() {
fmt.Println("Completed task Y by SubSvc2")
}
type SubSvc3 struct{}
func (svc *SubSvc3) DoZ() {
fmt.Println("Completed task Z by SubSvc3")
}
func main() {
a := NewAFacde()
a.DoSomething()
}
|
Output:
Start all tasks......
Completed task X by SubSvc1
Completed task Y by SubSvc2
Completed task Z by SubSvc3
Completed all tasks
Application Scenarios
- 解决易用性问题:对多个复杂的底层系统接口的组合;对细粒度接口的组合。
- 解决性能问题:通过增加一个中间层来减少对后端接口调用次数,减少网络延时。
- 架构边界设计:不完全架构边界(最终完整架构边界的临时替代品)实现策略的一种。
- 有没有发现这个代码结构与依赖注入的写法一致?
Referances
https://time.geekbang.org/column/article/206409
https://golangbyexample.com/facade-design-pattern-in-golang/
https://pkg.go.dev/github.com/google/wire