文章目录
【Java设计模式】中介者模式
一、概述
中介者设计模式旨在减少系统中多个对象或类之间通信的复杂性。它通过提供一个集中的中介者类来处理不同类之间的交互,从而减少它们之间的直接依赖。
二、详细解释及实际示例
- 实际示例:
- 想象一个繁忙机场的空中交通管制系统,其中空中交通管制员充当中介者。在这种情况下,许多飞机希望起飞、降落或在机场空域内导航。如果每个飞行员都直接与其他每个飞行员通信,可能会导致混乱和潜在的事故,而不是这样,所有通信都通过空中交通管制员进行。管制员接收请求,处理它们,并向每个飞行员给出清晰、有序的指令。这个集中式系统降低了通信的复杂性,确保了管理机场运营的安全性和效率。这类似于软件中的中介者设计模式,其中一个中央中介者类处理和协调不同对象或系统之间的交互。
- 通俗解释:
- 中介者通过强制一组类的通信流经一个中介对象来解耦它们。
- 维基百科解释:
- 在软件工程中,中介者模式定义了一个对象,该对象封装了一组对象的交互方式。由于它可以改变程序的运行行为,因此该模式被认为是一种行为模式。在面向对象编程中,程序通常由许多类组成。业务逻辑和计算分布在这些类中。然而,随着更多的类被添加到程序中,特别是在维护和/或重构期间,这些类之间的通信问题可能会变得更加复杂。这使得程序更难阅读和维护。此外,由于任何更改都可能影响其他几个类中的代码,因此更改程序可能会变得困难。使用中介者模式,对象之间的通信被封装在一个中介者对象中。对象不再直接相互通信,而是通过中介者进行通信。这减少了通信对象之间的依赖关系,从而减少了耦合。
三、Java中中介者模式的编程示例
在这个示例中,中介者封装了一组对象的交互方式。它们不是直接相互引用,而是使用中介者接口。
派对成员Rogue
、Wizard
、Hobbit
和Hunter
都继承自PartyMemberBase
并实现PartyMember
接口。
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
接口及其实现组成。
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);
}
}
这里是一个展示中介者模式实际应用的演示。
public static void main(String[] args) {
// 创建派对和成员
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);
}
运行示例的控制台输出如下。
14:05:15.081 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit joins the party
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard joins the party
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue joins the party
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter joins the party
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit spotted enemies
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard runs for cover
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue runs for cover
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter runs for cover
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard tells a tale
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit comes to listen
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue comes to listen
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter comes to listen
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue found gold
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit takes his share of the gold
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard takes his share of the gold
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter takes his share of the gold
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter hunted a rabbit
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit arrives for dinner
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard arrives for dinner
14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue arrives for dinner
四、中介者模式的详细解释及实际示例
五、何时在Java中使用中介者模式
当以下情况时使用中介者模式:
- 一组对象以定义良好但复杂的方式进行通信。由此产生的相互依赖关系是无结构的,难以理解。
- 由于对象引用并与许多其他对象通信,因此重用对象很困难。
- 分布在几个类中的行为应该是可定制的,而无需大量的子类化。
六、中介者模式在Java中的实际应用
- java.util.Timer的所有scheduleXXX()方法。
- java.util.concurrent.Executor#execute()。
- java.util.concurrent.ExecutorService的submit()和invokeXXX()方法。
- java.util.concurrent.ScheduledExecutorService的scheduleXXX()方法。
- java.lang.reflect.Method#invoke()。
- Java消息服务(JMS)使用中介者来处理客户端和服务器之间的消息交换。
- JavaBeans属性更改支持类(java.beans.PropertyChangeSupport)充当中介者,处理关于属性更改的bean之间的通信。
七、中介者模式的好处和权衡
好处:
- 减少程序组件之间的耦合,促进更好的组织和更易于维护。
- 集中控制。中介者模式集中了控制逻辑,使其更易于理解和管理。
权衡:
- 中介者可能会成为与系统中所有类耦合的上帝对象,承担过多的责任和复杂性。