【设计模式】9、facade 外观模式

文章目录

  • 九、外观模式
    • [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

https://www.codingexplorations.com/blog/design-pattern-series-understanding-the-facade-design-pattern-in-go

播放电影, 需要各个子系统共同参与, 这种过程式的代码太繁琐, 可以抽象出 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()
}
相关推荐
RedJACK~34 分钟前
Go Ebiten小游戏开发:扫雷
开发语言·后端·golang
研究司马懿2 小时前
【ETCD】ETCD——confd配置管理
数据库·golang·自动化·运维开发·etcd·argocd·gitops
王道长服务器 | 亚马逊云12 小时前
AWS + 苹果CMS:影视站建站的高效组合方案
服务器·数据库·搜索引擎·设计模式·云计算·aws
在未来等你13 小时前
AI Agent设计模式 Day 1:ReAct模式:推理与行动的完美结合
设计模式·llm·react·ai agent·plan-and-execute
钢门狂鸭1 天前
go开发规范指引
开发语言·驱动开发·golang
脚踏实地的大梦想家1 天前
【Go】P19 Go语言并发编程核心(三):从 Channel 安全到互斥锁
开发语言·安全·golang
乐悠小码1 天前
Java设计模式精讲---03建造者模式
java·设计模式·建造者模式
Tony Bai1 天前
Go GUI 开发的“绝境”与“破局”:2025 年现状与展望
开发语言·后端·golang
豆浆whisky1 天前
Go分布式追踪实战:从理论到OpenTelemetry集成|Go语言进阶(15)
开发语言·分布式·golang
Tony Bai1 天前
【Go模块构建与依赖管理】08 深入 Go Module Proxy 协议
开发语言·后端·golang