设计模式 -- 中介者模式和观察者模式

2019-06-18 00:00:00

如何优雅地简化对象之间的耦合关系?

前言

开发过程有个原则叫"最少知识原则",也就是说一个对象尽可能少得了解另外一个对象,这样才能降低耦合性,否则每一次改动都可能产生较多的关联影响。"中介者模式"和"发布订阅模式"很好地体现了"最少知识原则",并且它两有一些相似性,容易让人不好区分,所以现在放在一起进行讨论和学习。

中介者模式(mediator)

用一个中介对象来封装一系列的对象交互

优点:降低了对象间的耦合性,可以独立地修改它们之间的交互。

缺点:由于对象之间交互的复杂性转移到了中介对象,中介对象往往变得巨大和难维护。

介绍完中介者模式的概念以及它的优缺点,我们再来个场景试试代码。

需求是:有多个对象,当对象全部处于完成状态时,再执行余下操作。

// 中介者类
class Mediator {
    constructor () {
      this.partner = {}
      Array.from(arguments).forEach(key => this.partner[key] = false)
    }
    
    success (key) {
      this.partner[key] = true
      this.checkAllSuccess()
    }
    
    fail (key) {
      this.partner[key] = false
      this.checkAllSuccess()
    }
    
    checkAllSuccess () {
      console.log(!Object.values(this.partner).includes(false) ? '全部完成!' : '未全部完成!')
    }
}

// 对象类,用于生成有交互关系的对象
class Partner {
    constructor (name) {
      this.name = name
    }
    
    success () {
      mediator.success(this.name)
    }
    
    fail () {
      mediator.fail(this.name)
    }
}

let mediator = new Mediator('aa', 'bb')
let aa = new Partner('aa')
let bb = new Partner('bb')
aa.success()    // 未全部完成!
bb.success()    // 全部完成!

总结:当多个对象之间存在交互行为时,优先考虑采用中介者模式。

发布订阅者(观察者模式)

它定义了对象之间的一种一对多的依赖关系,当一个对象变化时,所有依赖的对象都讲得到通知。

使用发布订阅者的优点主要还是能够使对象之间解耦。

上个最简洁的使用框架

class Observer {
    subs = []
    
    add (obj) {
        this.subs.push(obj)
    }
    
    remove (key) {
        this.subs = this.subs.filter(obj => obj.key !== key)
    }
    
    notify () {
        subs.forEach(obj => {
            obj.fn()
        })
    }
}

let observer  = new Observer()
observer.add({
    key: 'a',
    fn: () => {console.log('a')}
})

observer.add({
    key: 'b',
    fn: () => {console.log('b')}
})

observer.notify()

总结

中介者和观察者很相似,相似就在于它两均有发布功能。两种的差别主要在于:中介者强调同事(colleague)类之间的交互,而发布订阅者强调目标改变之后对订阅者的统一通讯。我觉得应该可以说中介者包含了发布订阅者。中介者的用户可以订阅和发布,发布订阅则只有一处发布,用户只能订阅。

Gitalking ...

Markdown is supported

Be the first guy leaving a comment!