设计模式之中介者模式
顾名思义,买房和卖房的人一般会委托中介,而不是直接去找卖主,卖主也不会接触买主。
那么在设计模式中这个中介对象,就是简化原有对象之间的交互关系,降低对象间的耦合度,使原有对象之间不必相互了解。
如果像上面这样,对象与对象之间的交互形成了网状结构,各自相互依赖。关系很是复杂,有时候都不知道调用哪。
引入一个中介,就变成如下方式,所有对话都是通过中介,买主和中介是一对一,中介和其他对象一对多。
先提取中介的关键词: 中介对象,其他对象(多个)
假设有一个短信服务,需要判断是否额外要发邮件。
邮箱服务发送邮件后还需要额外判断是否需要发送短信。
如上图,两个服务存在交互关系,如果后面还有一个服务过来,短信服务需要额外判断还是否需要发送其他消息呢?
/**
* @author lw
* @date 2022/3/29 0029
* @description 短信服务
*/
public class SmsService implements SenderService{
SenderService mailService = null;
@Override
public void send(String type,String ...args) {
String toPhone = args[0];
String content = args[1];
System.out.println("短信发送:"+toPhone+"-->"+content);
if("all".equals(type)){
mailService.send(null,content);
}
}
}
/**
* @author lw
* @date 2022/3/29 0029
* @description 邮件服务
*/
public class MailService implements SenderService{
SenderService smsService = null;
@Override
public void send(String type,String ...args) {
String content = args[0];//如果是一个参数,那么就只是内容,就仅仅发邮件
if("all".equals(type)){
content = args[1];
smsService.send(null,args);
}
System.out.println("邮件发送:"+content);
}
}
我觉得应该不会有人这么定义吧,在MailService中关联SmsService,SmsService中关联MailService?
这样类与类真是太强耦合了。甚至在SmsService中还有if这种业务判断,如果后续还有其他参数,那么就真的很可能会形成1W行的发送短信代码。
调用者
String toPhone = "12306";
String content = "hello world";
SmsService smsService = new SmsService();
MailService mailService = new MailService();
smsService.mailService = mailService;
mailService.smsService = smsService;
/**
* 短信发送:12306-->hello world
邮件发送:hello world
*/
smsService.send("all",toPhone,content);
/**
* 短信发送:12306-->hello world
*/
smsService.send("sms",toPhone,content);
/**
* 短信发送:12306-->hello world
邮件发送:hello world
*/
mailService.send("all",toPhone,content);
/**
* 邮件发送:hello world
*/
mailService.send("mail",content);
按上面代码如此调用,虽然能正常工作,但现在要引入一个WeiXinService呢?
在SmsService和MailService中继续加一个WeixinService判断?
中介对象
引入中介者MiddleService后就如下所示,其实一直都用过,
/**
* @author lw
* @date 2022/4/2 0002
* @description 中介对象
*/
public class MiddleService {
SmsService smsService;
MailService mailService;
public void sendMsg(String type,String toPhone,String content){
if("all".equals(type)||"sms".equals(type)){
smsService.send(toPhone,content);
}
if("all".equals(type)||"mail".equals(type)){
mailService.send(content);
}
}
}
/**
* @author lw
* @date 2022/3/29 0029
* @description 短信服务
*/
public class SmsService implements SenderService{
@Override
public void send(String ...args) {
String toPhone = args[0];
String content = args[1];
System.out.println("短信发送:"+toPhone+"-->"+content);
}
}
/**
* @author lw
* @date 2022/3/29 0029
* @description 邮件服务
*/
public class MailService implements SenderService{
@Override
public void send(String ...args) {
String content = args[0];
System.out.println("邮件发送:"+content);
}
}
在SmsService和MailService中不再需要增加if判断,它就是单纯的发送短信和邮件。
而所有的判断都是在MiddleService中的。
如果以后增加了WeixinService,也只需要在MiddleService中增加if判断。
那么以后我们调用时,就只需要中介类即可,其他类和中介类都是一对一关系,调用者也不需要关心其他类是什么,有什么逻辑和内容,只需要知道把一切都告诉中介类就能完成任务。
调用者
String toPhone = "12306";
String content = "hello world";
MiddleService middleService = new MiddleService();
MailService mailService = new MailService();
SmsService smsService = new SmsService();
middleService.mailService = mailService;
middleService.smsService= smsService;
/**
* 短信发送:12306-->hello world
邮件发送:hello world
*/
middleService.sendMsg("all",toPhone,content);
/**
* 邮件发送:hello world
*/
middleService.sendMsg("mail",toPhone,content);
/**
* 短信发送:12306-->hello world
*/
middleService.sendMsg("sms",toPhone,content);
这样把SmsService和MailService委托给MiddleService,所有动作就由中介去操作。
但是从买主或者卖主考虑,我需要知道自己的中介是谁,此处对应SmsService和MailService,如果有人找到我想发送短信或者邮件,那我也可以交给中介处理啊。
所有,有如下的变体,不过这种变体我更想把它归类为访问者模式。
public class MailService implements SenderService{
MiddleService middleService = null;
@Override
public void send(String ...args) {
String content = args[0];
System.out.println("邮件发送:"+content);
}
public void sendMail(String content){
middleService.sendMsg("mail",null,content);
}
}
public class SmsService implements SenderService{
MiddleService middleService = null;
@Override
public void send(String ...args) {
String toPhone = args[0];
String content = args[1];
System.out.println("短信发送:"+toPhone+"-->"+content);
}
public void sendSms(String phone,String content){
middleService.sendMsg("sms",phone,content);
}
}
//调用
String toPhone = "12306";
String content = "hello world";
MiddleService middleService = new MiddleService();
MailService mailService = new MailService();
SmsService smsService = new SmsService();
middleService.mailService = mailService;
middleService.smsService= smsService;
mailService.middleService = middleService;
smsService.middleService = middleService;
mailService.sendMail(content);
smsService.sendSms(toPhone,content);
还记得访问者模式的UML图,类与类相互依赖,通过方法来首尾结束,上面其实更可以说是一个访问者模式。
总结
中介模式是为了解决对象与对象之间的强耦合性,将一对多,多对多关系变为和中介对象的一对一关系。
这个对象可以理解为类与类之间的关系,方法与方法之间的关系,变量与变量之间的关系。