Go设计模式(28)-中介者模式

中介者模式是设计模式系列中最后一个模式。这个模式我从未用过,主要原因是没碰到过合适的场景。如果大家有适合使用中介者模式的场景,中介者模式能帮大家更好的维护系统。

UML类图位置:https://www.processon.com/view/link/60d29bf3e401fd49502afd25

本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/28mediator.go

1.定义

1.1中介者模式

中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。

UML:

图片

1.2分析

对于定义,大家比较容易理解。由中介者控制所有的交互,Colleague对象无需相互感知。

使用中介者模式有个前提,Colleague之间相互影响,即一个Colleague的变化会影响其它Colleague。

我们再来看UML。通过UML可以看出

  • Mediator包含所有Colleague,这是中介者能控制所有交互的基础

  • Colleague包含Mediator,Colleague变化可直接通知Mediator,这是Colleague无需知道其它Colleague的基础,只需知道Mediator即可

根据前面提到的前提和UML类图,我们思考的再深一些,ConcreteColleague是否有相同父类并不重要,只要Mediator包含所有ConcreteColleague,ConcreteColleague有Mediator,中介者模式依然有效。

2.应用场景

使用中介者模式有哪些好处?

我们设想一种场景,假设有多个Colleague,分别为Colleague1、Colleague2、Colleague3、Colleague4,如果一个Colleague的动作会影响到其它Colleague,便形成多对多的网状结构,随着Colleague增加,会更加难以管理。如果使用中介者模式,会变成一对多的星状结构,所有Colleague只和Mediator相关,管理复杂度降低。

在实际工作中,没碰到过网状结构,所以没用过中介者模式。比较合适的例子,如GoLand中的注册,点击Active Goland/Evaluate for free,会显示不同的UI组件。

图片

图片

3.代码实现


我们简单实现GoLand激活的例子。

package main

import "fmt"

/**
 * @Author: Jason Pang
 * @Description: 中介者接口
 */
type Mediator interface {
  Process(colleague UIColleague)
}

/**
 * @Author: Jason Pang
 * @Description: 真正的中介者
 */
type UIMediator struct {
  activate *ActivateColleague
  evaluate *EvaluateColleague
  text     *TextColleague
}

/**
 * @Author: Jason Pang
 * @Description: 中介者大总管,处理所有事情
 * @receiver u
 */
func (u *UIMediator) Process(colleague UIColleague) {
  if colleague == u.activate { //如果是激活
    u.evaluate.Show("试用内容隐藏")
    u.text.Show("请输入激活码")
  } else if colleague == u.evaluate { //如果是试用
    u.activate.Show("激活内容隐藏")
    u.text.Show("请出入激活时间")
  }
}

/**
 * @Author: Jason Pang
 * @Description: Colleague接口
 */
type UIColleague interface {
  Action()
}

/**
 * @Author: Jason Pang
 * @Description: 激活UI
 */
type ActivateColleague struct {
  mediator Mediator
}

/**
 * @Author: Jason Pang
 * @Description: 激活触发的动作
 * @receiver a
 */
func (a *ActivateColleague) Action() {
  a.mediator.Process(a)
}

/**
 * @Author: Jason Pang
 * @Description: 激活UI显示内容
 * @receiver e
 * @param text
 */
func (e *ActivateColleague) Show(text string) {
  fmt.Println(text)
}

/**
 * @Author: Jason Pang
 * @Description: 试用UI
 */
type EvaluateColleague struct {
  mediator Mediator
}

/**
 * @Author: Jason Pang
 * @Description: 试用触发的动作
 * @receiver e
 */
func (e *EvaluateColleague) Action() {
  e.mediator.Process(e)
}

/**
 * @Author: Jason Pang
 * @Description: 试用UI显示内容
 * @receiver e
 * @param text
 */
func (e *EvaluateColleague) Show(text string) {
  fmt.Println(text)
}

/**
 * @Author: Jason Pang
 * @Description: 文案UI
 */
type TextColleague struct {
  mediator Mediator
}

/**
 * @Author: Jason Pang
 * @Description: 文案触发动作
 * @receiver t
 */
func (t *TextColleague) Action() {
  t.mediator.Process(t)
}

/**
 * @Author: Jason Pang
 * @Description: 文案显示内容
 * @receiver t
 * @param text
 */
func (t *TextColleague) Show(text string) {
  fmt.Println(text)
}

func main() {
  //初始化
  m := &UIMediator{}

  activate := &ActivateColleague{
    mediator: m,
  }
  evaluate := &EvaluateColleague{
    mediator: m,
  }
  text := &TextColleague{
    mediator: m,
  }

  m.activate = activate
  m.evaluate = evaluate
  m.text = text
  //点击激活
  fmt.Println("-----------------点击激活")
  activate.Action()
  //点击试用
  fmt.Println("-----------------点击试用")
  evaluate.Action()
}

输出:

-----------------点击激活

试用内容隐藏

请输入激活码

-----------------点击试用

激活内容隐藏

请出入激活时间

从代码中可以看出,Mediator有所有的UI,UI只调用Mediator,无需知道其它UI,Mediator通过Process处理所有操作。当今后增加新UI,只需Mediator知道即可,不必改动其它UI。当然,要防止Mediator变成超级大类,这需要根据实际情况做取舍。

总结

中介者模式算是聚而歼之的模式,因为从分而治之上讲,对应的操作应该让每一个Colleague自行管理,但这样做,Colleague之间需要相互了解,沟通成本太高。

如果收拢到Mediator,整体效率会高很多,但Mediator存在成为上帝类的可能,反而导致不好维护。

这是不是特别像实际生活。所以说世上的处理方案没有定法,能够更好的解决问题就是最好的。共勉。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员麻辣烫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值