Skip to content

外观模式 (Facade Pattern) ​

意图 ​

外观模式是结构型设计模式:加一个外观类,把子系统的一组接口收在自己名下,客户端只跟它打交道,不必逐个摸子系统的模块。

问题 ​

拿图形处理库打比方:它分成渲染、形状处理、颜色处理几个模块,客户端直接用,就得自己记住每个模块怎么调。

解决方案 ​

给这个库加一个外观接口,客户端只调 DrawColoredCircle、DrawColoredRectangle 这类方法,创建部件、填色、渲染的调用顺序由外观内部安排。

模式结构 ​

  1. 外观(Facade):提供一个高层接口,使得客户端可以通过这个接口访问子系统的功能。
  2. 子系统(Subsystem):表示一个或多个类,包含了子系统的具体功能。子系统并不知道外观的存在,它们只负责处理自己的工作。

代码 ​

下面是外观模式的 Go 实现:

go
package main

import "fmt"

// 子系统1 - 渲染
type Renderer struct{}

func (r *Renderer) RenderShape(shape string) {
    fmt.Println("渲染形状:", shape)
}

// 子系统2 - 形状处理
type ShapeMaker struct{}

func (s *ShapeMaker) CreateCircle() string {
    return "圆形"
}

func (s *ShapeMaker) CreateRectangle() string {
    return "矩形"
}

// 子系统3 - 颜色处理
type ColorFiller struct{}

func (c *ColorFiller) FillColor(shape, color string) {
    fmt.Println("为", shape, "填充颜色:", color)
}

// 外观
type GraphicFacade struct {
    renderer   *Renderer
    shapeMaker *ShapeMaker
    colorFiller *ColorFiller
}

func NewGraphicFacade() *GraphicFacade {
    return &GraphicFacade{
        renderer:   &Renderer{},
        shapeMaker: &ShapeMaker{},
        colorFiller: &ColorFiller{},
    }
}

func (g *GraphicFacade) DrawColoredCircle(color string) {
    shape := g.shapeMaker.CreateCircle()
    g.colorFiller.FillColor(shape, color)
    g.renderer.RenderShape(shape)
}

func (g *GraphicFacade) DrawColoredRectangle(color string) {
    shape := g.shapeMaker.CreateRectangle()
    g.colorFiller.FillColor(shape, color)
    g.renderer.RenderShape(shape)
}

func main() {
    graphic := NewGraphicFacade()

    fmt.Println("绘制红色圆形:")
    graphic.DrawColoredCircle("红色")

    fmt.Println("绘制蓝色矩形:")
    graphic.DrawColoredRectangle("蓝色")
}

适用场景 ​

  • 当需要为一个复杂子系统提供一个简单接口时。
  • 当需要减少子系统与客户端之间的耦合时。
  • 当需要将子系统的不同部分组织成一个高层接口时。

实现方式 ​

  1. 创建子系统类,包含子系统的具体功能。
  2. 创建外观类,持有子系统类的实例。
  3. 在外观类中,提供简化的接口,调用子系统类的功能。
  4. 客户端通过外观类与子系统交互,而不直接使用子系统类。

优缺点 ​

优点:

  • 客户端只认外观的几个方法,子系统换实现时调用方不用跟着改。
  • 调用顺序收在外观一处,客户端少背一半流程。

缺点:

  • 如果外观类实现得不好,可能会变得臃肿,成为上帝类。
  • 增加了额外的层次,可能会带来性能上的开销。

其他模式的关系 ​

  • 适配器模式(Adapter Pattern):适配器模式用于将一个接口转换为另一个接口,而外观模式用于简化子系统的使用,为子系统提供一个统一的接口。
  • 代理模式(Proxy Pattern):代理模式用于控制对对象的访问,而外观模式用于为子系统提供一个简单的接口。
  • 抽象工厂模式(Abstract Factory Pattern):抽象工厂模式可以与外观模式结合使用,为客户端提供一个创建子系统对象的高层接口。

参考资料 ​

同层页面 ​

相关页面 ​

Hello Golang