toBeTheLight.github.io 荒原

阅读:《图解设计模式》7 简单化


书中将 Facade 外观模式、Mediator 中介者模式归纳为简单化类关系的模式。 外观模式:为互相关联的一批类整理出一个统一对外的接口。 中介者模式:为一系列对象间的交互封装一个中介对象。

Facade 外观模式

定义

为互相关联在一起的错综复杂的类整理出一个接口,这些子系统更加容易被访问。外部程序不需要关心内部子系统的细节和相关关系。

角色

  • 外观:即向外提供接口的角色。
  • 其他角色:都能实现系统的部分功能。
  • 客户端:外观角色的使用者。

JavaScript 实现

// 其他角色
// database
class DataBase () {
  constructor () {
    this.assets = ''
    this.title = ''
    this.state = ''
  }
  async fetch () {
    const { assets, title, state } = fetch('some.path')
    this.assets = assets
    this.title = title
    this.state = state
  }
}
class Document () {
  constructor () {
    this.title = ''
    this.assets = ''
    this.root = ''
  }
  writeTitle (title) {
    this.title = `<title>${title}</title>`
  }
  writeAssets (assets) {
    this.assets = `<script src=${assets.script}></script>`
    this.assets += `<link href=${assets.css} />`
  }
  writeRoot (state) {
    this.root = render(state)
  }
  write () {
    return this.title + this.assets + this.root
  }
}
// 外观角色
class Maker {
  async makePage () {
    const database = new DataBase()
    await database.fetch()
    const document = new Document()
    document.writeTitle(database.title)
    document.writeAssets(database.assets)
    document.writeRoot(database.state)
    return document.write
  }
}
// 使用者
const maker = new Maker()
maker.makePage()

思考

  • 外观模式只是将多种组成角色融合为一个或多个对外提供完整功能的接口,所以只要有这种意图的都算是使用了外观模式。
  • 外观模式的目的是为了提供复杂系统的易使用的接口,所以一般不需要被继承复写,从而一般使用单例模式或静态方法。

Mediator 中介者模式

定义

为一系列对象间的交互封装一个中介对象,降低系列对象间的耦合。

角色

  • 抽象中介者:定义与同事进行通信的接口。
  • 具体中介者:实现抽象中介者接口。
  • 抽象同事:负责定义与中介角色进行通信的接口。
  • 具体同事:负责实现抽象同事定义的接口。

JavaScript 实现

我们以一个较为复杂的登录控件为例,使用伪代码做一版本实现。

// 抽象同事
class Plugin {
  constructor (manager) {
    this.manager = manager
  }
  init () {
    throw new Error('需实现 Plugin 类的 init 方法')
  }
  show () {
    throw new Error('需实现 Plugin 类的 show 方法')
  }
  hide () {
    throw new Error('需实现 Plugin 类的 hide 方法')
  }
}
// 具体同事
class Username extends Plugin {
  init () {
    // 初始化验证服务
    // 初始化交互行为
    if(login) {
      this.manager.success()
    }
    if (qrcodeClick) {
      this.manager.statusCenter('toQrcode')
    }
    if (forgetClick) {
      this.manager.statusCenter('toForget')
    }
  }
  show () {
    // display = 'block'
  }
  hide () {
    // display = 'none'
  }
}

class Qrcode extends Plugin {
  init () {
    // 开始扫码轮询
    if(login) {
      this.manager.success()
    }
    if (qrcodeClick) {
      this.manager.statusCenter('toQrcode')
    }
    if (forgetClick) {
      this.manager.statusCenter('toForget')
    }
  }
  show () {
    // display = 'block'
  }
  hide () {
    // display = 'none'
  }
}

// 抽象中介者
class Widget {
  constructor () {
    this.register()
    this.activate()
  }
  register () {
    throw new Error('需实现 Container 类的 register 方法')
  }
  activate () {
    throw new Error('需实现 Container 类的 activate 方法')
  }
  statusCenter () {
    throw new Error('需实现 Container 类的 statusCenter 方法')
  }
  success () {
    throw new Error('需实现 Container 类的 success 方法')
  }
}

// 具体中介者
class CommonWidget extends Widget {
  constructor () {
    super()
  }
  register () {
    this.plugins = {
      username: new Username(this),
      qrCode: new Qrcode(this)
    }
  }
  activate () {
    this.current = this.plugins[0]
    this.current.show()
  }
  success () {
    this.current.hide()
  }
  statusCenter (name) {
    if (name === 'toQrcode') {
      this.current.hide()
      this.plugins.qrCode.show()
    } else if (name === 'toForget') {
      window.href = '//sth.sth.sth/forget'
    }
  }
}
// 使用
new CommonWidget()

思考

可以从实例代码中看出

  • 各个对象之间是一无所知的,它们仅仅需要通知中介发生了什么事情,而由中介调用需要交互的其他对象,保证了对象的独立性。
  • 但随着系统内对象增多,之间交互变复杂,中介者对象要负责的职责就会剧增,从而导致中介者本身难以维护。
  • 归根到底,中介者充当的就是搅屎的角色。既然是搅屎的角色,就要保证系统中其他不方便做的事情要统统丢该它。

Content