我们平时写代码的过程,一个类必然会与其他类产生依赖关系,如果这种依赖关系如网状般错综复杂,那么必然会影响我们的代码逻辑以及执行效率,适当地使用中介者模式可以对这种依赖关系进行解耦使逻辑结构清晰,本篇博客,我们就一起学习中介者模式。
定义及使用场景
定义:中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。
使用场景:
当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时涉及很多其他对象的行为,可使用中介者模式。
UML类图
- Mediator:抽象中介者角色,定义了同事对象到中介者对象的接口,一般以抽象类的方式实现。
- ConcreteMediator:具体中介者角色,继承于抽象中介者,实现了父类定义的方法,它从具体的同事对象接受消息,向具体同事对象发出命令。
- Colleague:抽象同事类角色,定义了中介者对象的接口,它只知道中介者而不知道其他的同事对象。
- ConcreteColleague1、ConcreteColleague2:具体同事类角色,继承于抽象同事类,每个具体同事类都知道本身在小范围的行为,而不知道在大范围内的目的。
实例引入
假设现在有A、B、C建立了一个微信讨论组,他们有什么问题就在这里讨论,A在犹豫今天中午吃什么,A同学只要在讨论组里问一声就可以了,不必要直接去和B、C同学打交道,省去了很多麻烦事。怎么实现呢?
抽象中介者:
package com.dsguo.mediator;
public interface Mediator {
/**
* 发送消息
* @param p
* @param message
*/
void chat(People p, String message);
}
抽象同事类:
package com.dsguo.mediator;
/**
* 抽象同事类 -- 聊天人员
*/
public abstract class People {
private String name;
private Mediator mediator;
public People(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public String getName() {
return name;
}
public Mediator getMediator() {
return mediator;
}
public abstract void receive(String message);
public abstract void send(String message);
}
3个具体同事类:
package com.dsguo.mediator;
public class PeopleA extends People {
public PeopleA(Mediator mediator, String name) {
super(mediator, name);
}
@Override
public void receive(String message) {
System.out.println("[A] 收到消息:" + message);
}
@Override
public void send(String message) {
System.out.println("[A] 发出消息:" + message);
}
}
package com.dsguo.mediator;
public class PeopleB extends People {
public PeopleB(Mediator mediator, String name) {
super(mediator, name);
}
@Override
public void receive(String message) {
System.out.println("[B] 收到消息:" + message);
}
@Override
public void send(String message) {
System.out.println("[B] 发出消息:" + message);
}
}
package com.dsguo.mediator;
public class PeopleC extends People {
public PeopleC(Mediator mediator, String name) {
super(mediator, name);
}
@Override
public void receive(String message) {
System.out.println("[C] 收到消息:" + message);
}
@Override
public void send(String message) {
System.out.println("[C] 发出消息:" + message);
}
}
具体中介者实现:
package com.dsguo.mediator;
public class MessageMediator implements Mediator {
private PeopleA a;
private PeopleB b;
private PeopleC c;
public void setA(PeopleA a) {
this.a = a;
}
public void setB(PeopleB b) {
this.b = b;
}
public void setC(PeopleC c) {
this.c = c;
}
@Override
public void chat(People p, String message) {
if (p instanceof PeopleA) {
a.send(message);
b.receive(message);
c.receive(message);
} else if (p instanceof PeopleB) {
b.send(message);
a.receive(message);
c.receive(message);
} else if (p instanceof PeopleC) {
c.send(message);
a.receive(message);
b.receive(message);
}
}
}
具体测试类:
package com.dsguo.mediator;
public class Client {
public static void main(String[] args) {
MessageMediator mediator = new MessageMediator();
PeopleA a = new PeopleA(mediator,"A");
PeopleB b = new PeopleB(mediator, "B");
PeopleC c = new PeopleC(mediator, "C");
mediator.setA(a);
mediator.setB(b);
mediator.setC(c);
mediator.chat(a,"中午吃啥饭?");
System.out.println();
mediator.chat(b, "我想是豆腐");
System.out.println();
mediator.chat(c,"行,一起吃豆腐");
System.out.println();
}
运行结果:
[A] 发出消息:中午吃啥饭?
[B] 收到消息:中午吃啥饭?
[C] 收到消息:中午吃啥饭?
[B] 发出消息:我想是豆腐
[A] 收到消息:我想是豆腐
[C] 收到消息:我想是豆腐
[C] 发出消息:行,一起吃豆腐
[A] 收到消息:行,一起吃豆腐
[B] 收到消息:行,一起吃豆腐
总结
优点:
- 简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
- 各同事对象之间解耦:中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
缺点:中介者会庞大,变得复杂难以维护。
使用场景
- 对象间的交互虽定义明确然而非常复杂,导致一组对象彼此相互依赖而且难以理解。
- 因为对象引用了许多其他对象并与其通信,导致对象难以复用。
- 想要定制一个分布在多个类中的逻辑或者行为,又不想生成太多子类。