原理
定义一个中介对象,将一组对象之间的交互转成和中介对象的交互,避免对象之间的复杂交互
最佳实践
需求背景
假设我们有一个比较复杂的对话框,对话框中有很多控件,比如按钮、文本框、下拉框等。
当我们对某个控件进行操作的时候,其他控件会做出相应的反应,比如,我们在下拉框中选择“注册”,注册相关的控件就会显示在对话框中。如果我们在下拉框中选择“登陆”,登陆相关的控件就会显示在对话框中。
按照通常我们习惯的 UI 界面的开发方式,我们将刚刚的需求用代码实现出来,就是下面这个样子。在这种实现方式中,控件和控件之间互相操作、互相依赖。
代码实现一
type Button struct{}
func (b *Button) OnclickListener(f func()) {
f()
}
type InputText struct{}
func (t *InputText) GetContent() string {
return ""
}
type UIController struct {
LoginBut *Button
RegisterBut *Button
UserName *InputText
Password *InputText
}
func (c *UIController) StartApp() {
loginBut := new(Button)
registerBut := new(Button)
userNameInput := new(InputText)
passwordInput := new(InputText)
loginBut.OnclickListener(func() {
username := userNameInput.GetContent()
password := passwordInput.GetContent()
if username != "" && password != "" {
//登录逻辑...
}
})
registerBut.OnclickListener(func() {
username := userNameInput.GetContent()
password := passwordInput.GetContent()
if username != "" && password != "" {
//注册逻辑...
}
})
}
我们发现loginBut、registerBut对象和usernameInputText、passwordInputText都有交互,此时我们可以创建一个中介对象,
让loginBut、registerBut对象只和中介对象交互,不再和两个InputText组件交互,简化交互关系
代码实现二
type UIMediator struct {
LoginBut *Button
RegisterBut *Button
UserNameInputText *InputText
PasswordInputText *InputText
}
func (m *UIMediator) HandleEvent(eventName string) {
if eventName == "login" {
username := m.UserNameInputText.GetContent()
password := m.PasswordInputText.GetContent()
if username != "" && password != "" {
//登录逻辑...
}
} else if eventName == "register" {
username := m.UserNameInputText.GetContent()
password := m.PasswordInputText.GetContent()
if username != "" && password != "" {
//注册逻辑...
}
}
}
func (c *UIController) StartAppV2() {
loginBut := new(Button)
registerBut := new(Button)
userNameInput := new(InputText)
passwordInput := new(InputText)
mediator := new(UIMediator)
mediator.LoginBut = loginBut
mediator.RegisterBut = registerBut
mediator.UserNameInputText = userNameInput
mediator.PasswordInputText = passwordInput
loginBut.OnclickListener(func() {
mediator.HandleEvent("login")
})
registerBut.OnclickListener(func() {
mediator.HandleEvent("register")
})
}
此时,所有的组件对象都只需要和中介对象UIMediator交互,不再需要相互交互,简化对象之间的交互关系
从代码中我们可以看出,原本业务逻辑会分散在各个控件中,现在都集中到了中介类中。实际上,这样做既有好处,也有坏处。
好处是简化了控件之间的交互,坏处是中介类有可能会变成大而复杂的“上帝类”(God Class)。所以,在使用中介模式的时候,我们要根据实际的情况,平衡对象之间交互的复杂度和中介类本身的复杂度。