中介者模式——Mediator
案例展示——Mediator怎么用?
我们先来看这样一种场景:有一家宝马4s店,下面有三个部门:销售部门,采购部门,库存管理部门,这三个部门的职责分别是:
-
采购部门: 负责宝马汽车的采购。与销售部门沟通销售情况:销售的好多进几辆车,销售不好就少进几辆车;与库存管理部门沟通库存情况:扩大库存或者减少库存
-
库存管理部门: 负责库存管理。与采购部门沟通采购情况:库存太多少采购,库存太少多采购;与销售部门沟通销售情况:库存积压,倾销处理。
-
销售部门: 负责销售汽车。与采购部门和库存管理部门进行沟通:根据销售情况决定是否增加库存。
我们会发现,各个部门之间是相互交叉,相互依赖的,每一个模块都需要另外两个模块的信息支持,耦合度特别的高,现在给出设计的类图如下:
代码实现如下:
//采购管理
public class Purchase {
//采购宝马汽车
public void buyBaomaCar(int number) {
//访问库存
Stock stock = new Stock();
//访问销售
Sale sale = new Sale();
//电脑的销售情况
int saleStatus = sale.getSaleStatus();
if (saleStatus > 80) { //销售情况良好
System.out.println("采购宝马汽车:" + number + "台");
//库存增加
stock.increase(number);
} else { //销售情况不好
//折半采购
int buyNumber = number / 2;
System.out.println("采购宝马汽车:" + buyNumber + "台");
}
}
//不再采购宝马汽车
public void refuseBuyBaomaCar() {
System.out.println("不再采购宝马汽车。。。");
}
}
//库存管理
public class Stock {
//原始库存是100辆宝马车
private static int BAOMACAR_NUMBER = 100;
//库存增加
public void increase(int number) {
BAOMACAR_NUMBER = BAOMACAR_NUMBER + number;
System.out.println("库存数量为:" + BAOMACAR_NUMBER);
}
//库存降低
public void decrease(int number) {
BAOMACAR_NUMBER = BAOMACAR_NUMBER - number;
System.out.println("库存数量为:" + BAOMACAR_NUMBER);
}
//获得库存数量
public int getStockNumber() {
return BAOMACAR_NUMBER;
}
//存货太多,通知采购人员不要采购,销售人员尽快销售
public void clearStock() {
Purchase purchase = new Purchase();
Sale sale = new Sale();
System.out.println("清理存货数量为:" + BAOMACAR_NUMBER);
//要求销售人员折价销售
sale.offSale();
//要求采购人员不要采购
purchase.refuseBuyBaomaCar();
}
}
//销售管理
public class Sale {
//销售宝马汽车
public void sellBaomaCar(int number) {
//访问库存
Stock stock = new Stock();
//访问采购人员
Purchase purchase = new Purchase();
//库存不够销售,通知采购人员采购宝马汽车
if (stock.getStockNumber() < number) {
purchase.buyBaomaCar(number);
}
System.out.println("销售宝马汽车:" + number + "台");
stock.decrease(number);
}
//反馈销售情况
public int getSaleStatus() {
Random random = new Random(System.currentTimeMillis());
int saleStatus = random.nextInt(100);
System.out.println("宝马汽车的销售情况为:" + saleStatus);
return saleStatus;
}
//折价处理
public void offSale() {
//清理所有库存
Stock stock = new Stock();
System.out.println("半价销售宝马汽车" + stock.getStockNumber() + "台");
}
}
//在一个场景中运行得:
public class Client {
public static void main(String[] args) {
System.out.println("======采购人员采购宝马汽车======");
Purchase purchase = new Purchase();
purchase.buyBaomaCar(100);
System.out.println("======销售人员销售宝马汽车=======");
Sale sale = new Sale();
sale.sellBaomaCar(12);
System.out.println("======库房管理人员管理库存=======");
Stock stock = new Stock();
stock.clearStock();
}
}
//结果如下:
======采购人员采购宝马汽车======
宝马汽车的销售情况为:22
采购宝马汽车:50台
======销售人员销售宝马汽车=======
销售宝马汽车:12台
库存数量为:88
======库房管理人员管理库存=======
清理存货数量为:88
半价销售宝马汽车88台
不再采购宝马汽车。。。
虽然我们顺利的实现了功能,可是这样的设计有没有问题?肯定是有很大的问题的,前面已经说过,耦合度太高,每个类之间依赖太深,可扩展性太低。假如再加一个部门,比如说是监管部门,监管部门需要获取每个部门的情况,每个部门又要获得监管部门的反馈信息,那样所有的类都需要修改,类图之间出现蜘蛛网状结构,这种设计是很不合理的,如下图所示:
基于上述的情况,我们可以引入一个中间管理者对每个类之间的依赖进行管理。每个模块之间不再相互交流,要交流就通过中间管理者进行交流,每个模块只负责自己的业务逻辑,不属于自己的则丢给中间管理者来处理,如下图所示:
对上面的案例进行修改,下面是设计类图:
-
AbstractMediator:抽象的中介者,实现中介者的抽象定义。定义了一个事件方法execute()
-
Mediator:具体的中介者,实现了AbstractMediator中的execute()事件方法。可以根据业务的要求产生多个中介者,并划分中介者的职责。中介者中一般定义多个private方法,用来处理各个对象之间的依赖关系。
-
AbstractColleague:抽象同事类,可以让具体的实现类继承
下面是代码实现:
//抽象的中介者
public abstract class AbstractMediator {
protected Purchase purchase;
protected Sale sale;
protected Stock stock;
//构造函数
public AbstractMediator() {
purchase = new Purchase(this);
sale = new Sale(this);
stock = new Stock(this);
}
//事件方法:处理多个对象之间的关系
public abstract void execute(String str, Object...objects);
}
//具体中介者
public class Mediator extends AbstractMediator {
//事件方法
public void execute(String str, Object...objects) {
if (str.equals("purchase.buy")) { //采购宝马汽车
this.buyBaomaCar((Integer)objects[0]);
} else if (str.equals("sale.sell")) { //销售宝马汽车
this.sellBaomaCar((Integer)objects[0]);
} else if (str.equals("sale.offsell")) { //折价销售
this.offSell();
} else if (str.equals("stock.clear")) { //清仓处理
this.clearStock();
}
}
//采购宝马汽车
private void buyBaomaCar(int number) {
int saleStatus = super.sale.getSaleStatus();
if (saleStatus > 80) { //销售情况良好
System.out.println("采购宝马汽车:" + number + "台");
//库存增加
super.stock.increase(number);
} else { //销售情况不好
//折半采购
int buyNumber = number / 2;
System.out.println("采购宝马汽车:" + buyNumber + "台");
}
}
//销售宝马汽车
private void sellBaomaCar(int number) {
//库存不够销售,通知采购人员采购宝马汽车
if (super.stock.getStockNumber() < number) {
super.purchase.buyBaomaCar(number);
}
super.stock.decrease(number);
}
//折价销售
private void offSell() {
System.out.println("半价销售宝马汽车" + stock.getStockNumber() + "台");
}
//清仓处理
private void clearStock() {
//要求清仓销售
super.sale.offSale();
//要求采购人员不要采购
super.purchase.refuseBuyBaomaCar();
}
}
//抽象的同事类
public abstract class AbstractColleague {
protected AbstractMediator mediator;
public AbstractColleague(AbstractMediator mediator) {
this.mediator = mediator;
}
}
//采购管理
public class Purchase extends AbstractColleague{
//构造函数
public Purchase(AbstractMediator mediator) {
super(mediator);
}
//采购宝马汽车
public void buyBaomaCar(int number) {
super.mediator.execute("purchase.buy", number);
}
//不再采购宝马汽车
public void refuseBuyBaomaCar() {
System.out.println("不再采购宝马汽车。。。");
}
}
//库存管理
public class Stock extends AbstractColleague {
//原始库存是100辆宝马车
private static int BAOMACAR_NUMBER = 100;
public Stock(AbstractMediator mediator) {
super(mediator);
}
//库存增加
public void increase(int number) {
BAOMACAR_NUMBER = BAOMACAR_NUMBER + number;
System.out.println("库存数量为:" + BAOMACAR_NUMBER);
}
//库存降低
public void decrease(int number) {
BAOMACAR_NUMBER = BAOMACAR_NUMBER - number;
System.out.println("库存数量为:" + BAOMACAR_NUMBER);
}
//获得库存数量
public int getStockNumber() {
return BAOMACAR_NUMBER;
}
//存货太多,通知采购人员不要采购,销售人员尽快销售
public void clearStock() {
System.out.println("清理存货数量为:" + BAOMACAR_NUMBER);
super.mediator.execute("stock.clear");
}
}
//销售管理
public class Sale extends AbstractColleague{
public Sale(AbstractMediator mediator) {
super(mediator);
}
//销售宝马汽车
public void sellBaomaCar(int number) {
super.mediator.execute("sale.sell", number);
System.out.println("销售宝马汽车:" + number + "台");
}
//反馈销售情况
public int getSaleStatus() {
Random random = new Random(System.currentTimeMillis());
int saleStatus = random.nextInt(100);
System.out.println("宝马汽车的销售情况为:" + saleStatus);
return saleStatus;
}
//折价处理
public void offSale() {
super.mediator.execute("sale.offsell");
}
}
//在一个场景中运行得:
public class Client {
public static void main(String[] args) {
AbstractMediator mediator = new Mediator();
System.out.println("======采购人员采购电脑=====");
Purchase purchase = new Purchase(mediator);
purchase.buyBaomaCar(100);
System.out.println("======销售人员销售电脑======");
Sale sale = new Sale(mediator);
sale.sellBaomaCar(1);
System.out.println("======库房管理人员管理库存======");
Stock stock = new Stock(mediator);
stock.clearStock();
}
}
//结果如下:
======采购人员采购电脑=====
宝马汽车的销售情况为:27
采购宝马汽车:50台
======销售人员销售电脑======
库存数量为:99
销售宝马汽车:1台
======库房管理人员管理库存======
清理存货数量为:99
半价销售宝马汽车99台
不再采购宝马汽车。。。
加入一个中介者,将与自己无关的活动交给中介者进行处理,设计结构更加清晰,而且类与类之间的耦合性大大减少,可扩展性大大增强。
深入分析——Mediator是什么?
Mediator的定义
定义: 用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示的相互作用,从而使其耦合松散,而且可以独立的改变它们之间的交互。如下是通用类图:
-
Mediator抽象中介者角色: 定义统一的接口,用于各同事角色之间的交互
-
ConcreateMediator具体中介者角色: 通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。
-
Colleague同事角色: 通过中介者与其他同事角色进行通信。每个同事类的行为分为两种:
- 第一种:自己本身的行为,比如改变对象本身的状态,处理自己的行为等,这种行为叫做自发行为,与其他的同时类或中介者没有任何的依赖
- 第二种:必须依赖中介者才能完成的行为,叫做依赖方法
Mediator的应用
中介者模式适用于对象之间紧密耦合的情况,紧密耦合的标准是:在类图之间出现可蜘蛛网状结构。
参考
《设计模式之禅》