文章目录
- 九、外观模式
-
- [9.1 player](#9.1 player)
-
- [9.1.1 player_test.go](#9.1.1 player_test.go)
- [9.1.2 player.go](#9.1.2 player.go)
- [9.2 login_register](#9.2 login_register)
-
- [9.2.1 account_test.go](#9.2.1 account_test.go)
- [9.2.2 account.go](#9.2.2 account.go)
九、外观模式
https://refactoringguru.cn/design-patterns/facade
如果有一个复杂的系统, 内部有很多子系统, 可以用 facade 封装一层, 只暴露出用户关心的简单接口.
注意: 随着需求增多, 不要做一个大而全的 facade, 而可以做多个小而美的 facade.
优点: 封装一层, 对外部用户屏蔽细节, 简化使用
缺点: 容易让所有系统, 都和 facade 耦合, 从而无法区分.
9.1 player
播放电影, 需要各个子系统共同参与, 这种过程式的代码太繁琐, 可以抽象出 facade, 简化用户的操作
bash
09facade/091player
├── player.go
├── player_test.go
└── readme.md
9.1.1 player_test.go
go
package _91player
import "testing"
/*
=== RUN TestPlayMovie
开始播放电影...
Playing audio...
Playing video...
Showing screen...
结束播放电影...
--- PASS: TestPlayMovie (0.00s)
PASS
*/
func TestPlayMovie(t *testing.T) {
f := &MultimediaFacade{
audioPlayer: &AudioPlayer{},
videoPlayer: &VideoPlayer{},
screenManager: &ScreenManager{},
}
f.PlayMovie()
}
9.1.2 player.go
go
package _91player
import (
"fmt"
)
// AudioPlayer 子系统
type AudioPlayer struct{}
func (a *AudioPlayer) PlayAudio() {
fmt.Println("Playing audio...")
}
// VudioPlayer 子系统
type VideoPlayer struct{}
func (v *VideoPlayer) PlayVideo() {
fmt.Println("Playing video...")
}
// ScreenManager 子系统
type ScreenManager struct{}
func (s *ScreenManager) ShowScreen() {
fmt.Println("Showing screen...")
}
// MultimediaFacade 外观
type MultimediaFacade struct {
audioPlayer *AudioPlayer
videoPlayer *VideoPlayer
screenManager *ScreenManager
}
func (f *MultimediaFacade) PlayMovie() {
fmt.Println("开始播放电影...")
f.audioPlayer.PlayAudio()
f.videoPlayer.PlayVideo()
f.screenManager.ShowScreen()
fmt.Println("结束播放电影...")
}
9.2 login_register
网站都提供登录, 注册两种方式, 用户经常分不清楚
现在很多 APP 都提供了登录或注册功能, 即只需要输入手机号即可. 内部的逻辑是:
- 如果未注册, 则注册并登录
- 如果已注册, 则登录
可以提供一个 facade, 实现[登录或注册]的功能
bash
09facade/092login_register
├── account.go
├── account_test.go
└── readme.md
9.2.1 account_test.go
go
package _92login_register
import (
"testing"
)
/*
=== RUN TestAccount
登录或注册
登录
--- PASS: TestAccount (0.00s)
PASS
*/
func TestAccount(t *testing.T) {
a := &accountFacadeService{service: &accountService{}}
a.loginOrRegister()
}
9.2.2 account.go
go
package _92login_register
import "fmt"
type iAccount interface {
login()
register()
}
type iAccountFacade interface {
loginOrRegister()
}
type accountService struct{}
func (s *accountService) login() {
fmt.Println("登录")
}
func (s *accountService) register() {
fmt.Println("注册")
}
// 是否已注册
func (s *accountService) isRegistered() bool {
return true
}
type accountFacadeService struct {
service *accountService
}
func (s *accountFacadeService) loginOrRegister() {
fmt.Println("登录或注册")
if !s.service.isRegistered() {
s.service.register()
}
s.service.login()
}