咱们好,这里是每周都在陪你一同进步的网管~!今天继续规划形式学习之旅,这次咱们分享个咱们每天都在用,但面试时常常忽视它的规划形式–外观形式,咱们一同来看看吧。

现代的软件体系都非常复杂,尽管咱们现已想尽一切办法将其“分而治之”,把一个体系划分为好几个较小的子体系了,但是仍然或许会存在这样的问题:子体系内有非常多的类,客户端往往需求和许多目标打交道之后才干完结想要完结的功用。

形式的由来

在咱们的日子中医院便是这样的。一般的医院都会分为挂号、门诊、化验、收费、取药等。看病的患者要想治好自己的病(相当于一个客户端想要完成自己的功用)就要和医院的各个部门打交道。首先,患者需求挂号,然后门诊,假如医师要求化验的话,患者就要去化验,然后再回到门诊室,最后拿药,经过一系列复杂的进程后才干完结看病的进程。如下图所示:

外观模式,一个每天都在用,却被多数人忽略的模式
假如咱们在医院设立一个接待员的话,患者只负责和接待员触摸,由接待员负责与医院的各个部门打交道,如下图所示:
外观模式,一个每天都在用,却被多数人忽略的模式
医院设立的接待员的角色便是咱们今天要介绍的外观形式,体系经过引进外观形式让需求调用多个子体系各自部分的功用接口以完结的需求,变为调用方只需求跟外观提供的一致功用进行交互即可。

外观模式,一个每天都在用,却被多数人忽略的模式

形式界说

外观形式又称为门面形式,它是一种结构型形式。引进外观形式后调用方与多个子体系的通讯有必要经过一个一致的外观目标进行,外观形式为子体系中的功用接口提供一个一致的界面,此形式界说了一个高层接口,这个接口使得这些子体系愈加容易使用。

外观形式的结构

外观形式的结构其实很简单,用一个UML图就能描述清楚外观形式里拥有哪些角色以及它们各自的特点,下面咱们看一下外观形式的类结构。

外观模式,一个每天都在用,却被多数人忽略的模式

外观形式编程完成

下面咱们用Go代码完成一个外观形式。

这个比如里咱们把电脑拥有的CPU、内容和硬盘视为子体系,调用方想发动电脑就得别离发动这三个子体系才行,所以咱们在子体系上增加一个外观目标,让调用方直接调用外观目标,由外观目标再去别离对接子体系最终完结电脑的发动。

该实例源代码引证自:github.com/yksz/go-des…

package main
import (
	"fmt"
)
const (
	BOOT_ADDRESS = 0
	BOOT_SECTOR  = 0
	SECTOR_SIZE  = 0
)
type CPU struct{}
func (c *CPU) Freeze() {
	fmt.Println("CPU.Freeze()")
}
func (c *CPU) Jump(position int) {
	fmt.Println("CPU.Jump()")
}
func (c *CPU) Execute() {
	fmt.Println("CPU.Execute()")
}
type Memory struct{}
func (m *Memory) Load(position int, data []byte) {
	fmt.Println("Memory.Load()")
}
type HardDrive struct{}
func (hd *HardDrive) Read(lba int, size int) []byte {
	fmt.Println("HardDrive.Read()")
	return make([]byte, 0)
}
type ComputerFacade struct {
	processor *CPU
	ram       *Memory
	hd        *HardDrive
}
func NewComputerFacade() *ComputerFacade {
	return &ComputerFacade{new(CPU), new(Memory), new(HardDrive)}
}
func (c *ComputerFacade) start() {
	c.processor.Freeze()
	c.ram.Load(BOOT_ADDRESS, c.hd.Read(BOOT_SECTOR, SECTOR_SIZE))
	c.processor.Jump(BOOT_ADDRESS)
	c.processor.Execute()
}
func main() {
	computer := NewComputerFacade()
	computer.start()
}

本文的完好源码,现已同步录入到我收拾的电子教程里啦,可向我的大众号「网管叨bi叨」发送关键字【规划形式】领取。

外观模式,一个每天都在用,却被多数人忽略的模式

使用外观形式的知名库

要说外观形式在实践开发中的使用,首先让我想起来的便是Java 里的Slf4j,它是一个抽象层,让用户对日志的操作一致由Slf4j跟用户去对接,用户用这个抽象层的API来写日志, 底层具体用什么日志东西完成用户完全不必关怀,由Slf4j来对接Log4j、LogBack 这些日志东西,这样就可以更方便地移植了。

外观模式,一个每天都在用,却被多数人忽略的模式
这个抽象层 Slf4j 便是Simple logging Facade For Java 的简称,从姓名里咱们也能看出来,它是一个外观形式的实践使用,因为普及度很高,许多解说外观形式的教程里都会提及它,拿它的完成来给读者做剖析。

总结

外观形式的优点

  • 简化了调用进程,不必深入了解子体系,以防给子体系带来危险。
  • 减少体系依靠,松散耦合。
  • 更好地划分访问层次,提高了安全性。
  • 遵从迪米特规律

外观形式的缺陷

  • 当增加子体系和扩展子体系行为时,需求对外观进行重复更改,不符合开闭原则,或许容易带来未知危险。

参考链接:

  • cdf.wiki/posts/37575…
  • www.kancloud.cn/digest/xing…
  • github.com/yksz/go-des…