一句话理解 :
我们交换 名片, 有事 告诉我 找谁,我处理
-
首先是我的名片
你拿着我的名片才能有事告诉我 也就是说你要包含我的引用对吧
-
接下来是你们的名片
你们要把名片给我 是不是太多不好拿 我是不是要有个文件夹
-
你啥时候把名片给我
你可以在创建的时候给我 (在构造方法中) 也可以创建完成后在给我(单独在写个方法)
这里我们在构造方法中给
- 怎末告诉我找谁类
当你想找我是不是要拿我名片打我电话
调用我的方法告诉我 找谁 干啥 (至少有两个参数 吧)
这样理解的话可以简单的分析出中介者模式的结构
- 抽象中介者(Mediator):定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
- 中介者实现类(Concrete Mediator):从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
- 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。(有的时候不需要这个角色)
- 同事类(Concrete Colleague):如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
类图
为什么要使用中介者模式
一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。
如果引入中介者模式,那么同事类之间的关系将变为星型结构,从图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。
是不是还有点不理解 看完下面这个例子在来讨论
中介模式之(打麻将)
- 抽象中介者
/**
* 抽象中介类 定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信
*/
public interface Finance {
void register(String name, Players players);
void command(String name,Integer number);
}
- 具体中介者
import java.util.HashMap;
import java.util.Map;
/**
* 老板娘 用来管钱
*/
public class Landlady implements Finance {
private Map<String,Players> map = new HashMap<String , Players>();
@Override
public void register(String name, Players players) {
map.put(name,players);
}
@Override
public void command(String name, Integer number) {
map.get(name).collectMoney(number);
}
}
- 抽象同事类
/**
* 抽象同事类 规定行为 也可以写成抽象类 把中介类的引用写在抽象类里
*/
public interface Players {
void collectMoney(Integer number); //收钱
void pay(String name,Integer number); //付钱给中介类
}
- 具体同事类
/**
* 东方位玩家
*/
public class East implements Players {
private Finance finance; //持有中介者(老板娘)的引用
private Integer moneyCount; //每个人的钱
private String name;
public East(Finance finance, Integer moneyCount, String name) {
this.finance = finance;
this.moneyCount = moneyCount;
this.name = name;
this.finance.register(this.name, this);
}
/**
* 收入
*
* @param number
*/
@Override
public void collectMoney(Integer number) {
this.moneyCount += number;
}
/**
* 支出
*
* @param name
* @param number
*/
@Override
public void pay(String name, Integer number) {
if (this.moneyCount <= number) {
System.out.println(this.name + "无力支付费用换人");
this.finance.command(name, this.moneyCount);
this.moneyCount = 0;
} else {
this.moneyCount -= number;
this.finance.command(name, number);
}
}
@Override
public String toString() {
return "East{" +
"finance=" + finance +
", moneyCount=" + moneyCount +
", name='" + name + '\'' +
'}';
}
}
/**
* 西方位玩家
*/
public class West implements Players {
private Finance finance; //持有中介者(总经理)的引用
private Integer moneyCount; //每个人的钱
private String name;
public West(Finance finance, Integer moneyCount, String name) {
this.finance = finance;
this.moneyCount = moneyCount;
this.name = name;
this.finance.register(this.name, this);
}
/**
* 收入
*
* @param number
*/
@Override
public void collectMoney(Integer number) {
this.moneyCount += number;
}
/**
* 支出
*
* @param name
* @param number
*/
@Override
public void pay(String name, Integer number) {
if (this.moneyCount <= number) {
System.out.println(this.name + "无力支付费用换人");
this.finance.command(name, this.moneyCount);
this.moneyCount = 0;
} else {
this.moneyCount -= number;
this.finance.command(name, number);
}
}
@Override
public String toString() {
return "West{" +
"finance=" + finance +
", moneyCount=" + moneyCount +
", name='" + name + '\'' +
'}';
}
}
南北省略 写法一样
- 客户端 麻将房
/**
* 当增加玩家或者减少玩家的时候不用去在原来的类里添加与之对应的方法
* 当需要给钱时只需要把钱给中介(老板娘) 老板娘负责进行给钱的操作
* 但是会增加中介类的负担 当中介类出问题时就会导致瘫痪(老板娘只收钱不给钱 一会就打钱来了)
*/
public class Client {
public static void main(String[] args) {
/**
* 开始打麻将了 老板娘在旁变看着
*/
Landlady landlady = new Landlady();
/**
* 四个位置坐上了人 每个人50元
*/
East east = new East(landlady, 50, "东");
West west = new West(landlady, 50, "西");
South south = new South(landlady, 50, "南");
North north = new North(landlady, 50, "北");
/**
* 西玩家点了东玩家炮给东10元
*/
west.pay("东", 10);
System.out.println(west);
System.out.println(east);
/**
* 东玩家暗杠明杠自摸
*/
north.pay("东", 45);
west.pay("东", 45);
south.pay("东", 45);
System.out.println(west);
System.out.println(east);
System.out.println(north);
System.out.println(south);
}
}
- 结果
West{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=40, name='西'}
East{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=60, name='东'}
西无力支付费用换人
West{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=0, name='西'}
East{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=190, name='东'}
North{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=5, name='北'}
South{finance=com.nwk.mediator.PlayPoker.Landlady@49476842, moneyCount=5, name='南'}
看到这 可能中介模式没学会 满脑子都是打麻将了吧
醒醒吧 学习了
现在再说说 为什么要使用中介者模式
1. 当增加玩家或者减少玩家的时候不用去在原来的类里添加与之对应的方法
2. 当需要给钱时只需要把钱给中介(老板娘) 老板娘负责进行给钱的操作
3. 但是会增加中介类的负担 当中介类出问题时就会导致瘫痪(老板娘只收钱不给钱 一会就打钱来了)
用打麻将说就是
1、减少给钱和找钱的时间 (可以多打两把)
2、防止因为钱的事扯皮(方便换人)
用系统来说
1、降低了类的复杂度,将一对多转化成了一对一。
2、各个类之间的解耦。
以下来自 菜鸟教程 https://www.runoob.com/design-pattern/mediator-pattern.html
意图:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
主要解决:对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
何时使用:多个类相互耦合,形成了网状结构。
如何解决:将上述网状结构分离为星型结构。
关键代码:对象 Colleague 之间的通信封装到一个类中单独处理。
应用实例: 1、中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。 2、机场调度系统。 3、MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。
优点: 1、降低了类的复杂度,将一对多转化成了一对一。 2、各个类之间的解耦。 3、符合迪米特原则。
缺点:中介者会庞大,变得复杂难以维护。
使用场景: 1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。 2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
注意事项:不应当在职责混乱的时候使用。