定义
中介者(Mediator)模式又称又叫调停模式,定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合变得松散,且可以独立地改变它们之间的交互。它是迪米特法则的典型应用。
中介者模式属于对象行为型模式。
要点
优点:
- 降低了对象之间的耦合性,使得对象易于独立地被复用。
- 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
缺点:
- 当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
主要角色:
抽象中介者(Mediator):它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
具体中介者(ConcreteMediator):实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
抽象同事类(Colleague):定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
具体同事类(Concrete Colleague):抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
场景
小明和小张使用微信进行聊天,他们需要先注册微信账户,聊天信息通过微信服务器转发到对方的移动设备。
实现
Mediator
/**
* 抽象中介者
*/
public interface Mediator {
/**
* 注册同事类
*/
void register(AbstractColleague colleague);
/**
* 转发消息
*/
void relay(AbstractColleague colleague);
}
WeChatMediator
/**
* 具体中介者
*/
public class WeChatMediator implements Mediator {
private List<AbstractColleague> colleagues = new ArrayList<>();
@Override
public void register(AbstractColleague colleague) {
if (!colleagues.contains(colleague)) {
colleagues.add(colleague);
colleague.setMediator(this);
}
}
@Override
public void relay(AbstractColleague colleague) {
AbstractColleague.Message message = colleague.getMessage();
colleagues.forEach(aColleague -> {
if (aColleague.getUsername().equals(message.getReceiver())) {
aColleague.receive(message);
}
});
}
}
AbstractColleague
/**
* 抽象同事类
*/
public abstract class AbstractColleague {
/**
* 绑定中介者
*/
protected Mediator mediator;
/**
* 同事类姓名
*/
protected String username;
/**
* 通信消息
*/
protected Message message;
public AbstractColleague(String username) {
this.username = username;
}
/**
* 接收消息
*/
public abstract void receive(Message message);
/**
* 发送消息
*/
public abstract void send(String receiver, String content);
public Message getMessage() {
return message;
}
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
public String getUsername() {
return username;
}
/**
* 同事类进行沟通的消息
*/
class Message {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 消息发送者
*/
private String sender;
/**
* 消息接收者
*/
private String receiver;
/**
* 消息内容
*/
private String content;
/**
* 消息发送时间
*/
private String sendTime;
public Message(String receiver, String content) {
this.sender = AbstractColleague.this.username;
this.receiver = receiver;
this.content = content;
this.sendTime = dateFormat.format(Calendar.getInstance().getTime());
}
public String getContent() {
return content;
}
public String getSendTime() {
return sendTime;
}
public String getSender() {
return sender;
}
public String getReceiver() {
return receiver;
}
}
}
ConcreteColleague
/**
* 具体同事类
*/
public class ConcreteColleague extends AbstractColleague{
public ConcreteColleague(String username) {
super(username);
}
@Override
public void receive(Message message) {
System.out.println(String.format("[%s] 已接收:%s [%s发送于:%s]\n", username, message.getContent(), message.getSender(), message.getSendTime()));
}
@Override
public void send(String receiver, String content) {
message = new Message(receiver, content);
System.out.println(String.format("[%s] 发送给 [%s]:%s", username, receiver, content));
mediator.relay(this);
}
}
Client
public class Client {
public static void main(String[] args) {
// 中介者
Mediator mediator = new WeChatMediator();
// 同事
AbstractColleague alice = new ConcreteColleague("Alice");
AbstractColleague bob = new ConcreteColleague("Bob");
AbstractColleague john = new ConcreteColleague("John");
// 注册
mediator.register(alice);
mediator.register(bob);
mediator.register(john);
// 通信
alice.send("Bob", "明天是你生日,祝你生日快乐!");
bob.send("Alice", "谢谢你!我的好朋友!");
bob.send("John", "周末有空一起打球?");
john.send("Bob", "好呀,不见不散!");
}
}
源码
总结
适用场景:
- 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
- 当想创建一个运行于多个类之间的对象,又不想生成新的子类时。