外观模式 (Facade Pattern)
意图
外观模式是结构型设计模式:加一个外观类,把子系统的一组接口收在自己名下,客户端只跟它打交道,不必逐个摸子系统的模块。
问题
拿图形处理库打比方:它分成渲染、形状处理、颜色处理几个模块,客户端直接用,就得自己记住每个模块怎么调。
解决方案
给这个库加一个外观接口,客户端只调 DrawColoredCircle、DrawColoredRectangle 这类方法,创建部件、填色、渲染的调用顺序由外观内部安排。
模式结构
- 外观(Facade):提供一个高层接口,使得客户端可以通过这个接口访问子系统的功能。
- 子系统(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("蓝色")
}适用场景
- 当需要为一个复杂子系统提供一个简单接口时。
- 当需要减少子系统与客户端之间的耦合时。
- 当需要将子系统的不同部分组织成一个高层接口时。
实现方式
- 创建子系统类,包含子系统的具体功能。
- 创建外观类,持有子系统类的实例。
- 在外观类中,提供简化的接口,调用子系统类的功能。
- 客户端通过外观类与子系统交互,而不直接使用子系统类。
优缺点
优点:
- 客户端只认外观的几个方法,子系统换实现时调用方不用跟着改。
- 调用顺序收在外观一处,客户端少背一半流程。
缺点:
- 如果外观类实现得不好,可能会变得臃肿,成为上帝类。
- 增加了额外的层次,可能会带来性能上的开销。
其他模式的关系
- 适配器模式(Adapter Pattern):适配器模式用于将一个接口转换为另一个接口,而外观模式用于简化子系统的使用,为子系统提供一个统一的接口。
- 代理模式(Proxy Pattern):代理模式用于控制对对象的访问,而外观模式用于为子系统提供一个简单的接口。
- 抽象工厂模式(Abstract Factory Pattern):抽象工厂模式可以与外观模式结合使用,为客户端提供一个创建子系统对象的高层接口。