〇、小故事
小王大学毕业了,打算来北京闯荡一下,于是就先寄宿到了他的表姐家,白天的时候,自己在外面小区转一转,看看能不能找到可以租到的房子,他找了好几天都没有找到合适的,要么就是小区里一张租房子的广告都没有,好不容易找到几个,里面的房间大小和价格又不合适。北京实在是太大了,而且这边人生地不熟的,找房子真的是耗费了他大量的力气。
到了周末,表姐问他这几天都在干嘛,他告诉了表姐自己找房子的经历,表姐跟他说,明天姐带你去找中介,这个事儿好办。第二天,小王和表姐到了某中介公司,跟中介表明自己需要寻找什么样的房子——主卧还是次卧
、屋子面积多少平米
、是否向阳
、房子在哪个区域内
、押金是多少
…… 根据这些条件,中介给小王列出了好几个房源,然后就带着他们去看房,很快小王就找到了自己心仪的房子了。
那么,上面的故事也是很多北漂人比较熟悉的经历吧。那么,对于房东和租客来说,中介人员就属于一个中间层,房东们与中介联系,将自己待出租的房子录入中介系统中,而访客又会通过中介去找房子,对于房子信息的采集,归类,降价,涨价,下架,匹配……这一系列工作都由中介人员去做,这样既使得房东很轻松,不用一次次对接房客,一遍遍的介绍自己的房子;也使得房客很轻松,直接通过中介系统就可以过滤出符合自己的房子,然后直奔目标,不用像个无头苍蝇一般的在各个小区乱碰运气的找房子。那么这个就是我们今天要介绍的设计模式——中介者模式。
一、模式定义
中介者模式(Mediator Pattern
)
使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
为了便于理解,我们再举一个系统设计上的例子。在网上售卖商城的系统中,存在三个功能,分别为采购功能、销售功能和库存功能。
【采购功能】需要从销售功能获取到销售情况,并且确定是否要继续采购增加库存量。
【销售功能】要获得库存信息,并且销售量大于库存量,则需要通知采购功能快速采购商品。并且每当销售了产品后,需要扣减库存。
【库存功能】如果库存压力大了,要提示销售功能去折价促销,尽快消耗库存,并且通知采购功能暂时不要进行该商品的采购行为。
通过上面的描述,我们应该可以看到,采购
、销售
和库存
这三个业务域是互相依赖的,如下图所示:
那么如果依照这种关联关系进行开发的话,就会出现这三个功能相互耦合的情况。如果需求变更了,会产生牵一发而动全身的情况发生。无形之中增加了业务开发量。那么针对这种情况,我们可以采取中介者模式或者叫做调停者模式。如下所示:
根据最小知识原则,无论是采购、销售还是库存,在他们眼中,最亲密的朋友都是这个中介者。而中介者将所有的业务逻辑关系进行整合,只需要这三个业务域提供针对他们自己业务的操作接口接口,后续如果需求变更,大概率涉及到修改的也都是在中介者。
二、模式类图
针对上面讲的网上售卖商城例子,我们来画一下类的关系图。首先,创建3个类分别为Purchase(采购人员
)、Sale(销售人员
)和Stock(库存人员
),其次,创建一个抽象的同事类
AbstractColleague,让刚刚创建的这3种人员都继承这个抽象类,该抽象类没有抽象方法需要子类实现,只是禁止本类被实例化成对象。在该抽象类中,引用了一个中介者类
Mediator,该类引用了Purchase、Sale和Stock这三种工作人员,并且把他们的调用逻辑抽取出来放到中介者类中。请见下图所示:
三、代码实现
创建抽象同事类,并引用中介者Mediator的实例对象:AbstractColleague.java
public abstract class AbstractColleague {
protected Mediator mediator;
public AbstractColleague(Mediator mediator) {
this.mediator = mediator;
}
}
创建采购人员:Purchase.java
public class Purchase extends AbstractColleague {
public Purchase(Mediator mediator) {
super(mediator);
}
/** 采购电脑 */
public void buyComputer(int num) {
System.out.println();
super.mediator.purchaseByComputer(num);
}
/** 不再采购电脑 */
public void refuseBuyComputer() {
System.out.println("不再采购电脑!");
}
}
创建销售人员:Sale.java
public class Sale extends AbstractColleague {
public Sale(Mediator mediator) {
super(mediator);
}
/** 销售电脑 */
public void sellComputer(int number) {
super.mediator.saleSellComputer(number);
System.out.println("销售电脑" + number + "台");
}
/** 获得销售情况(即:售卖了多少台电脑) */
public int getSaleStatus() {
// 模拟销售数量
int sellNumber = new Random(System.currentTimeMillis()).nextInt(100);
System.out.println("电脑的销售情况为:" + sellNumber + "台");
return sellNumber;
}
/** 折价处理 */
public void offSale() {
super.mediator.saleOffSale();
}
}
创建库存人员:Stock.java
public class Stock extends AbstractColleague {
private static int COMPUTER_NUM = 100;
public Stock(Mediator mediator) {
super(mediator);
}
/** 增加库存 */
public void increaseComputer(int number) {
COMPUTER_NUM += number;
System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
}
/** 减少库存 */
public void decreaseComputer(int number) {
COMPUTER_NUM -= number;
System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
}
/** 获得当前库存 */
public int getStockNumber() {
return COMPUTER_NUM;
}
/** 清理库存 */
public void clearStock() {
System.out.println("清理库存数量为:" + COMPUTER_NUM);
super.mediator.stockClear();
}
}
创建中介者:Mediator.java
public class Mediator {
protected Purchase purchase; // 采购人员
protected Sale sale; // 销售人员
protected Stock stock; // 库存人员
public Mediator() {
purchase = new Purchase(this);
sale = new Sale(this);
stock = new Stock(this);
}
/** 采购电脑 */
public void purchaseByComputer(int num) {
int saleStatus = sale.getSaleStatus();
// 如果销售情况不好(即:没有超过80台),则采购总数减半
String msg = "";
if (saleStatus