引子
小帅在一家制造业企业工作,他所在的生产部门负责产品的的生产。由于他们公司的产品都是定制化的,都是根据销售部门的订单生产,在生产的过程中还要检查仓库里的原材料是否充足。
如果原材料不够还要通知采购部门去采购,采购部门采购完了之后还要通知仓库入库,仓库再通知生产部门提料生产。
最后生产完成之后,生产部还要通知仓库进行产成品入库。
整个生产过程涉及到多个部门的互相协作,各种关系错综复杂,各部门之间的关系图如下:
小帅发现各部门之间强耦合,每个部门的对象都要引用其他很多部门的对象,各部门类很难复用。于是小帅向老板建议成立项目管理部,负责和各个部门沟通,每个部门只要和项目管理部沟通就行了,这样部门之间的关系就清晰了很多:
老板觉得小帅的这个提议很好,采纳了小帅的建议,成立了项目管理部负责和生产相关的各个环节,顺便提拔小帅为项目管理部经理,让他放开手脚大干一场。
小帅心中窃喜,这种模式也不是我的原创,我只是应用了中介者模式而已。
中介者模式
中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
简单点说中介者模式就是:所有的对象只认识中介者,只和中介者对象交互。
- Mediator(中介者):中介者定义一个接口与各个同事(Colleague)对象通信。
- ConcreteMediator(具体中介者):具体中介者通过协调各同事对象实现协作行为,了解并维护他的各个同事。
- Colleague(同事类):每个同事类都知道它的中介者对象,并且只与中介者对象通信。
同事向同一个中介者对象发送和接收请求。中介者在各个同事间适当地转发请求以实现协作行为。
小帅应用了中介者模式之后,列出了生产相关的所有代码:
部门抽象类:
/**
* 部门抽象类
*/
public abstract class Department {
/**
* 中介类
*/
Mediator mediator;
public Department(Mediator mediator) {
this.mediator = mediator;
}
}
市场部门:
/**
* 市场部门
*/
public class MarketingDepartment extends Department{
public MarketingDepartment(Mediator mediator) {
super(mediator);
}
/**
* 通知生产
*/
public void notifyProduction() {
super.mediator.notify(this, "开始生产");
}
}
生产部门:
/**
* 生产部门
*/
public class ProductionDepartment extends Department{
public ProductionDepartment(Mediator mediator) {
super(mediator);
}
/**
* 生产产品
*/
public void production() {
System.out.println("生产产品");
}
/**
* 通知采购
*/
public void notificationPurchase() {
super.mediator.notify(this, "通知采购");
}
/**
* 通知入库
*/
public void notificationStorage() {
super.mediator.notify(this, "通知入库");
}
}
采购部门:
/**
* 采购部门
*/
public class PurchasingDepartment extends Department{
public PurchasingDepartment(Mediator mediator) {
super(mediator);
}
/**
* 采购原材料
*/
public void purchaseRawMaterials() {
System.out.println("采购原材料");
}
/**
* 通知入库
*/
public void notificationStorage() {
super.mediator.notify(this, "通知入库");
}
}
仓库:
/**
* 仓库
*/
public class Warehouse extends Department{
public Warehouse(Mediator mediator) {
super(mediator);
}
/**
* 原材料入库
*/
public void rawMaterialStorage() {
System.out.println("原材料入库");
}
/**
* 产成品入库
*/
public void finishedProductStorage() {
System.out.println("产成品入库");
}
/**
* 通知提料
*/
public void notificationExtractRowMaterials() {
super.mediator.notify(this, "通知提料");
}
}
中介者接口:
/**
* 中介者接口
*/
public interface Mediator {
/**
* 通知方法
* @param department
* @param event
*/
void notify(Department department, String event);
}
项目管理部:
/**
* 项目管理部
*/
public class ProjectManagementMediator implements Mediator{
private MarketingDepartment marketingDepartment;
private ProductionDepartment productionDepartment;
private PurchasingDepartment purchasingDepartment;
private Warehouse warehouse;
public ProjectManagementMediator() {
this.marketingDepartment = new MarketingDepartment(this);
this.productionDepartment = new ProductionDepartment(this);
this.purchasingDepartment = new PurchasingDepartment(this);
this.warehouse = new Warehouse(this);
}
@Override
public void notify(Department department, String event) {
// 市场部的通知
if(department instanceof MarketingDepartment) {
this.productionDepartment.production();
}
// 生产部的通知
else if(department instanceof ProductionDepartment) {
if("通知采购".equals(event)) {
this.purchasingDepartment.purchaseRawMaterials();
} else if("通知入库".equals(event)) {
this.warehouse.finishedProductStorage();
}
}
// 采购部的通知
else if(department instanceof PurchasingDepartment) {
if("通知入库".equals(event)) {
this.warehouse.rawMaterialStorage();
}
}
// 仓库的通知
else if(department instanceof Warehouse) {
if("通知提料".equals(event)) {
this.productionDepartment.production();
}
}
}
}
客户端:
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
// 项目管理部
Mediator mediator = new ProjectManagementMediator();
// 市场部
MarketingDepartment marketingDepartment = new MarketingDepartment(mediator);
// 通知生产
marketingDepartment.notifyProduction();
// 生产部
ProductionDepartment productionDepartment = new ProductionDepartment(mediator);
// 通知采购
productionDepartment.notificationPurchase();
// 采购部
PurchasingDepartment purchasingDepartment = new PurchasingDepartment(mediator);
// 通知入库
purchasingDepartment.notificationStorage();
// 仓库
Warehouse warehouse = new Warehouse(mediator);
// 通知提料
warehouse.notificationExtractRowMaterials();
// 生产部通知入库
productionDepartment.notificationStorage();
}
}
输出:
生产产品
采购原材料
原材料入库
生产产品
产成品入库
这样,所有的部门只需要把自己的需求提给项目管理部,让项目管理部充当中介和其他部门沟通,统一管理,统筹,就能大大提高生产效率。
总结
中介者和观察者模式的区别
中介者的主要目标是消除一系列对象之间的相互依赖,这些对象将依赖于同一个中介者对象。
观察者的目标是在对象之间建立动态的单向连接,它们之间的交互关系往往都是单向的,一个参与者要么是观察者,要么是被观察者,不会兼具两种身份。
最重要的是它们的意图是不一样的,中介者主要是为了消除对象之间的依赖;而观察者模式是一种订阅机制,它主要是为了发通知给订阅对象。
我们要区分不同的设计模式,最好还是从他们的意图出发,不同的设计模式可能很相似,但是它们要解决的问题是不一样的。
最后,我们来看一下中介者模式的优缺点:
优点
- 减少了子类的生成,Mediator将Colleague对象的行为组织在一起,如果要改变Colleague对象的行为模式只需新增个Mediator的子类就行了,各个Colleague类可以复用。
- 将各个Colleague对象解耦,所有的Colleague对象之间都没有关联,我们可以独立地改变和复用各个Mediator类和Colleague类。
- 简化了对象之间的关系,将原来的多对多关系变成Mediator和各Colleague对象之间的一对多关系。
缺点
- 中介者模式将交互的复杂性转变为中介者的复杂性,中介者对象可能会变的越来越复杂,难以维护。