中介者模式是设计模式系列中最后一个模式。这个模式我从未用过,主要原因是没碰到过合适的场景。如果大家有适合使用中介者模式的场景,中介者模式能帮大家更好的维护系统。
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/
往期文章回顾:
- 设计模式
- 招聘
- 思考
- 存储
- 算法系列
- 读书笔记
- 小工具
- 架构
- 网络
- Go语言
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://sigusoft.com/goland/1530.html