目的
定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。
解释
真实世界的例子
流氓、巫师、霍比特人和猎人决定联手并参加同一个政党。为了避免每个成员彼此耦合,他们使用政党这个接口进行相互通信。
通俗地说
中介者模式通过强制通信流,利用中介对象从而实现对一组类的解耦。
维基百科说
在软件工程中,中介者模式定义了一个对象,该对象封装了一系列对象之间的交互。此模式被认为是一种行为型模式,因为它可以改变程序的运行行为。在面向对象的编程中,程序通常由许多类组成,业务逻辑和计算分布在这些类中。但是,随着更多的类被添加到程序中,特别是在维护或重构期间,这些类之间的通信问题可能会变得更加复杂。这使得程序更难阅读和维护。此外,更改程序可能会变得很困难,因为任何更改都可能影响其他几个类中的代码。使用中介者模式,对象之间的通信被封装在中介对象中。对象不再直接相互通信,而是通过中介进行通信。这减少了通信对象之间的依赖关系,从而减少了耦合。
程序示例
在此示例中,中介者模式封装了一系列对象之间的交互。他们不是直接相互引用,而是使用中介接口。
政党成员 Rogue, Wizard, Hobbit, 和 Hunter 都继承自 PartyMemberBase 实现 PartyMember 接口。
java
public interface PartyMember {
void joinedParty(Party party);
void partyAction(Action action);
void act(Action action);
}
@Slf4j
public abstract class PartyMemberBase implements PartyMember {
protected Party party;
@Override
public void joinedParty(Party party) {
LOGGER.info("{} joins the party", this);
this.party = party;
}
@Override
public void partyAction(Action action) {
LOGGER.info("{} {}", this, action.getDescription());
}
@Override
public void act(Action action) {
if (party != null) {
LOGGER.info("{} {}", this, action);
party.act(this, action);
}
}
@Override
public abstract String toString();
}
public class Rogue extends PartyMemberBase {
@Override
public String toString() {
return "Rogue";
}
}
// Wizard、Hobbit和Hunter的实现方式类似我们的中介系统由 Party 接口及其实现组成。
java
public interface Party {
void addMember(PartyMember member);
void act(PartyMember actor, Action action);
}
public class PartyImpl implements Party {
private final List<PartyMember> members;
public PartyImpl() {
members = new ArrayList<>();
}
@Override
public void act(PartyMember actor, Action action) {
for (var member : members) {
if (!member.equals(actor)) {
member.partyAction(action);
}
}
}
@Override
public void addMember(PartyMember member) {
members.add(member);
member.joinedParty(this);
}
}下面演示了中介者模式的实际应用。
java
// 创建政党和政党成员
Party party = new PartyImpl();
var hobbit = new Hobbit();
var wizard = new Wizard();
var rogue = new Rogue();
var hunter = new Hunter();
// 添加政党成员
party.addMember(hobbit);
party.addMember(wizard);
party.addMember(rogue);
party.addMember(hunter);
// 执行行动->其他政党成员
// 由政党通知
hobbit.act(Action.ENEMY);
wizard.act(Action.TALE);
rogue.act(Action.GOLD);
hunter.act(Action.HUNT);下面是运行该示例的控制台输出。
Hobbit joins the party
Wizard joins the party
Rogue joins the party
Hunter joins the party
Hobbit spotted enemies
Wizard runs for cover
Rogue runs for cover
Hunter runs for cover
Wizard tells a tale
Hobbit comes to listen
Rogue comes to listen
Hunter comes to listen
Rogue found gold
Hobbit takes his share of the gold
Wizard takes his share of the gold
Hunter takes his share of the gold
Hunter hunted a rabbit
Hobbit arrives for dinner
Wizard arrives for dinner
Rogue arrives for dinner类图

适用性
在以下情况下使用中介者模式
- 系统中对象之间存在着明确但比较复杂的引用关系,导致它们之间的依赖关系结构混乱并且难以理解。
- 一个对象引用许多其他对象并与之通信,导致难以复用该对象。
- 想通过一个自定义类来封装多个类中的行为,而又不想生成太多的子类。
已知使用
- All scheduleXXX() methods of java.util.Timer
- java.util.concurrent.Executor#execute()
- submit() and invokeXXX() methods of java.util.concurrent.ExecutorService
- scheduleXXX() methods of java.util.concurrent.ScheduledExecutorService
- java.lang.reflect.Method#invoke()