概念

外观模式又叫门面模式,是一种常用的封装模式

给一系列具有关联性的子系统的集合提供对外访问的一组接口,调用者不用明确内部具体的业务逻辑,只需要调用这组接口达到目的即可。也就是要求子系统外部与内部不能直接进行通讯,必须通过一个统一的对象进行,而这个统一的对象就是门面。门面模式通过只提供高层次的接口,从而降低了外部与子系统调用的复杂性。

使用场景

A. 为一组子系统或一系列复杂的模块提供一个统一的外部访问的接口。

B. 调用方与子系统依赖性很强,通过门面将 client 与子系统强依赖转化门面对象间的依赖。

优点

  • 减少了系统的相互依赖性;在我看来通过门面的代理,直接切断了调用方与各个子系统内部的调用关系,降低了双方的耦合关系,从而降低了系统混乱、依赖。直接将两者的依赖关系转移到门面对象之间的依赖,减少了直接与子系统间的相互依赖关系,符合设计原则。

  • 功能拓展性更灵活,只要不影响门面对象,子系统内部可以多样性。

  • 通过门面对外只提供必要的服务与直接对外暴露子系统服务而言,系统的安全性更高。

缺点

不满足开闭原则,外观修改风险性很大。

代码实现

文件结构

├── facade.go
├── facade_test.go
├── policeInspection.go
├── samplefacade.go
└── sampleletters.go

facade.go

package facade

type Facade interface {
	sendLetter(context, address string)
}

sampleletters.go

type SampleLetters struct {
	letter string
}

func (sl *SampleLetters) WriteLetters(content string) {
	sl.letter = fmt.Sprintf("信件内容为:%s", content)
}

func (sl *SampleLetters) AddAddress(address string) {
	sl.letter += "\n" + fmt.Sprintf("邮寄至:%s", address)
}

func (sl *SampleLetters) PutIntoEnvelope() {
	fmt.Println("信件放入信封中...")
}

func (sl *SampleLetters) SendLetters() {
	fmt.Println("信件已发送....")
}

simlefacade.go

type SampleFacade struct {
	SampleLetters
	PoliceInspection
}

func NewSampleFacade() *SampleFacade {
	return &SampleFacade{}
}

func (sf *SampleFacade) sendLetter(content, address string) {
	sf.WriteLetters(content)
	sf.AddAddress(address)

	ok := sf.CheckLetterSecurity(sf.letter)
	if !ok {
		fmt.Println("信件内容不安全")
		return
	}
	fmt.Println("信件内容很安全")

	sf.PutIntoEnvelope()
	sf.SendLetters()
}

policeinspection.go

type PoliceInspection struct{}

func (PoliceInspection) CheckLetterSecurity(content string) bool {
	fmt.Printf("被检查内容:%s\n", content)
	fmt.Println("内容检查通过...")
	return true
}

代码测试

func TestNewFacade(t *testing.T) {
	var facade Facade = NewSampleFacade()
	facade.sendLetter(
		"Hello dear, facade design pattern...",
		"example@example.cn",
	)
}

测试结果

=== RUN   TestNewFacade
被检查内容:Hello dear, facade design pattern...
内容检查通过...
信件内容很安全
信件放入信封中...
信件已发送....
--- PASS: TestNewFacade (0.00s)
PASS
ok      ginstudy/facade 0.004s