设计模式之中介者模式
什么是中介者模式呢?顾明思议,就是起到一个中间者的作用,可以负责协调各方的问题。
举例:现在有A部门、B部门、C部门、D部门,而每两个部门之间都会存在一些交集,当新增一个E部门的时候,同样要跟其他几个部门打交道,太过繁琐。这个时候多么希望有一个中间部门专门负责打交道的事情,这样A-E部门只需要跟这个部门打交道,且只负责完成自己部门的事情,需要其他部门配合的事情交由中间部门处理。而这个中间部门就是一个中介者模式。
代码如下:
public class Mediator_01 {
//人事部
static class PersonnelDept{
public void registerEmployee(){
System.out.println("人事部:新员工入职登记,并领取办公用品");
this.offerEmplyeeData();
this.applyOffices();
}
public void acceptOffices(){
System.out.println("人事部:领取采购部门提供的办公用品");
}
private void applyOffices(){
System.out.println("人事部:向采购部门申请办公用品!");
new PurchasingDept().auditPassApply();
}
private void offerEmplyeeData(){
System.out.println("人事部:提供员工信息(主要是薪资和银行卡)给财务");
new FinanceDept().recordSalaries();
}
}
//财务部
static class FinanceDept{
public void recordSalaries(){
System.out.println("财务部:财务部门登记了新同事的薪水!");
}
public void auditPassApply(){
System.out.println("财务部:通过办公用品采购资金的申请!");
this.offerMoney();
}
private void offerMoney(){
System.out.println("财务部:将采购资金划拨到采购部门");
new PurchasingDept().acceptMoney();
}
}
//采购部
static class PurchasingDept{
public void auditPassApply(){
System.out.println("采购部:通过办公用品的申请!");
this.applyMoney();
}
public void acceptMoney(){
System.out.println("采购部:接受到财务部门划拨的采购资金了!");
this.purchasing();
new PersonnelDept().acceptOffices();
}
private void applyMoney(){
System.out.println("采购部:向财务部门申请资金!");
new FinanceDept().auditPassApply();
}
private void purchasing(){
System.out.println("采购部:采购办公用品!");
}
}
public static void main(String[] args) {
PersonnelDept personnelDept = new PersonnelDept();
personnelDept.registerEmployee();
}
}
打印结果如下:
人事部:新员工入职登记,并领取办公用品
人事部:提供员工信息(主要是薪资和银行卡)给财务
财务部:财务部门登记了新同事的薪水!
人事部:向采购部门申请办公用品!
采购部:通过办公用品的申请!
采购部:向财务部门申请资金!
财务部:通过办公用品采购资金的申请!
财务部:将采购资金划拨到采购部门
采购部:接受到财务部门划拨的采购资金了!
采购部:采购办公用品!
人事部:领取采购部门提供的办公用品
以上就是不使用中介模式,从一个员工入职登记,到领取办公用品中间经历的环节,这里主要描述的是由一个新入职员工引起的三个部门之间的彼此的交互情况。
从以上代码,可以知道,这三个部门之间的耦合度很高,都在各自的方法中调用了其他部门的方法,这样并不利于代码的维护,一旦对应的类进行了扩展,比如由一个子类来重写了方法的逻辑,那么对应使用到这个逻辑的类初始化,以及调用方法都要发生改变,如果使用的地方很多,那么改动起来是一个相当大的工程,还有可能会存在遗漏的情况。
此时,能够有一个专门来协调这些事宜的部门,那该多好,比如:人事部实际只能处理员工的入职登记和办公用品的申请,具体的薪水登记和办公用品的提供并不能由人事部控制,为了不让其跟其他两个部门打交道(降低耦合),这部分的逻辑由我们的中间部门来完成,我们只需要调用中间部门提供的对应方法即可,所以重构代码如下:
public class Mediator_02 {
//人事部
static class PersonnelDept{
private MediatorDept mediatorDept;
public PersonnelDept(MediatorDept mediatorDept){
this.mediatorDept = mediatorDept;
}
public void joinCompany(){
System.out.println("人事部:新员工入职登记,并领取办公用品");
mediatorDept.recordSalaries();
}
public void acceptOffices(){
System.out.println("人事部:领取采购部门提供的办公用品");
}
public void applyOffices(){
System.out.println("人事部:向采购部门申请办公用品!");
mediatorDept.offerOffices();
this.acceptOffices();
}
}
//财务部
static class FinanceDept{
private MediatorDept mediatorDept;
public FinanceDept(MediatorDept mediatorDept){
this.mediatorDept = mediatorDept;
}
public void recordSalaries(){
System.out.println("财务部:财务部门登记了新同事的薪水!");
}
public void auditPassApply(){
System.out.println("财务部:通过办公用品采购资金的申请!");
this.offerMoney();
}
public void offerMoney(){
System.out.println("财务部:将采购资金划拨到采购部门");
}
}
//采购部
static class PurchasingDept{
private MediatorDept mediatorDept;
public PurchasingDept(MediatorDept mediatorDept){
this.mediatorDept = mediatorDept;
}
public void auditPassApply(){
System.out.println("采购部:通过办公用品的申请!");
//申请采购资金
this.applyMoney();
//采购办公用品
this.purchasing();
}
public void acceptMoney(){
System.out.println("采购部:接受到财务部门划拨的采购资金了!");
}
public void applyMoney(){
System.out.println("采购部:向财务部门申请资金!");
mediatorDept.offerMoney();
this.acceptMoney();
}
private void purchasing(){
System.out.println("采购部:采购办公用品!");
}
}
//中间部门(协调部门)
static class MediatorDept{
//人事部
private PersonnelDept personnelDept;
//财务部
private FinanceDept financeDept;
//采购部
private PurchasingDept purchasingDept;
//员工加入公司
public void recordSalaries(){
//登记员工薪水以及银行账户
financeDept.recordSalaries();
}
//提供办公用品
public void offerOffices(){
//通过办公用品的申请
purchasingDept.auditPassApply();
}
//提供采购资金
public void offerMoney(){
//通过采购资金的申请
financeDept.auditPassApply();
}
public void setPersonnelDept(PersonnelDept personnelDept) {
this.personnelDept = personnelDept;
}
public void setFinanceDept(FinanceDept financeDept) {
this.financeDept = financeDept;
}
public void setPurchasingDept(PurchasingDept purchasingDept) {
this.purchasingDept = purchasingDept;
}
}
public static void main(String[] args) {
MediatorDept mediatorDept = new MediatorDept();
//人事部
PersonnelDept personnelDept = new PersonnelDept(mediatorDept);
//财务部
FinanceDept financeDept = new FinanceDept(mediatorDept);
//采购部
PurchasingDept purchasingDept = new PurchasingDept(mediatorDept);
mediatorDept.setFinanceDept(financeDept);
mediatorDept.setPersonnelDept(personnelDept);
mediatorDept.setPurchasingDept(purchasingDept);
//人事部新员工入职
personnelDept.joinCompany();
//给新员工申请办公用品
personnelDept.applyOffices();
}
}
打印结果不变,但是在调用上我们引入了一个中间者的概念,这个中间者负责处理我们自己不能处理的逻辑,我们只负责调用即可,不需要关心具体的逻辑,即使后续类名称、类方法、方法逻辑发生了变更对我们都是透明的,不会影响到现有的代码。
如上所说,中间部门中的方法具体怎么实现的,各部门并不会关心,很可能后期中间部门会进行扩展,方法中的逻辑会变更,也有可能创建一个新的类来实现新的逻辑,那这个时候我不希望因为我使用了新的类名,从而要去修改各部门之间依赖的中间部门类。那就要用到java的继承,让所有的具体的中间部门类,都去继承一个统一的抽象中间部门类,而各个部门之间由原来依赖的具体类,修改为依赖抽象类,这样不论是换成那个中间部门类,其他部门类中的代码都不用修改。修改代码如下:
public class Mediator_03 {
//抽象中间部门
static abstract class AbstrackMediatorDept{
//人事部
private PersonnelDept personnelDept;
//财务部
private FinanceDept financeDept;
//采购部
private PurchasingDept purchasingDept;
public PersonnelDept getPersonnelDept() {
return personnelDept;
}
public void setPersonnelDept(PersonnelDept personnelDept) {
this.personnelDept = personnelDept;
}
public FinanceDept getFinanceDept() {
return financeDept;
}
public void setFinanceDept(FinanceDept financeDept) {
this.financeDept = financeDept;
}
public PurchasingDept getPurchasingDept() {
return purchasingDept;
}
public void setPurchasingDept(PurchasingDept purchasingDept) {
this.purchasingDept = purchasingDept;
}
public abstract void recordSalaries();
public abstract void offerOffices();
public abstract void offerMoney();
}
//具体中间部门(协调部门)
static class MediatorDept extends AbstrackMediatorDept{
//员工加入公司
@Override
public void recordSalaries(){
//登记员工薪水以及银行账户
super.financeDept.recordSalaries();
}
//提供办公用品
@Override
public void offerOffices(){
//通过办公用品的申请
super.purchasingDept.auditPassApply();
}
//提供采购资金
@Override
public void offerMoney(){
//通过采购资金的申请
super.financeDept.auditPassApply();
}
}
//抽象部门类
static abstract class AbstractDept{
private AbstrackMediatorDept abstrackMediatorDept;
public AbstractDept(AbstrackMediatorDept abstrackMediatorDept){
this.abstrackMediatorDept = abstrackMediatorDept;
}
}
//人事部
static class PersonnelDept extends AbstractDept{
public PersonnelDept(AbstrackMediatorDept abstrackMediatorDept){
super(abstrackMediatorDept);
}
public void joinCompany(){
System.out.println("人事部:新员工入职登记,并领取办公用品");
super.abstrackMediatorDept.recordSalaries();
}
public void acceptOffices(){
System.out.println("人事部:领取采购部门提供的办公用品");
}
public void applyOffices(){
System.out.println("人事部:向采购部门申请办公用品!");
super.abstrackMediatorDept.offerOffices();
this.acceptOffices();
}
}
//财务部
static class FinanceDept extends AbstractDept{
public FinanceDept(AbstrackMediatorDept abstrackMediatorDept){
super(abstrackMediatorDept);
}
public void recordSalaries(){
System.out.println("财务部:财务部门登记了新同事的薪水!");
}
public void auditPassApply(){
System.out.println("财务部:通过办公用品采购资金的申请!");
this.offerMoney();
}
public void offerMoney(){
System.out.println("财务部:将采购资金划拨到采购部门");
}
}
//采购部
static class PurchasingDept extends AbstractDept{
public PurchasingDept(AbstrackMediatorDept abstrackMediatorDept){
super(abstrackMediatorDept);
}
public void auditPassApply(){
System.out.println("采购部:通过办公用品的申请!");
//申请采购资金
this.applyMoney();
//采购办公用品
this.purchasing();
}
public void acceptMoney(){
System.out.println("采购部:接受到财务部门划拨的采购资金了!");
}
public void applyMoney(){
System.out.println("采购部:向财务部门申请资金!");
super.abstrackMediatorDept.offerMoney();
this.acceptMoney();
}
private void purchasing(){
System.out.println("采购部:采购办公用品!");
}
}
public static void main(String[] args) {
AbstrackMediatorDept abstrackMediatorDept = new MediatorDept();
//人事部
PersonnelDept personnelDept = new PersonnelDept(abstrackMediatorDept);
//财务部
FinanceDept financeDept = new FinanceDept(abstrackMediatorDept);
//采购部
PurchasingDept purchasingDept = new PurchasingDept(abstrackMediatorDept);
abstrackMediatorDept.setFinanceDept(financeDept);
abstrackMediatorDept.setPersonnelDept(personnelDept);
abstrackMediatorDept.setPurchasingDept(purchasingDept);
//人事部新员工入职
personnelDept.joinCompany();
//给新员工申请办公用品
personnelDept.applyOffices();
}
}
以上就是中介者模式的代码实现。
下面看一看中介者模式的定义:用一个中介对象封装一系列的对象交互,中介者使各个对象之间不需要显示的相互调用,从而使其耦合松散,而且可以独立的改变它们之间的交互。
优点:
减少类之间的相互依赖,降低了类之间的耦合
缺点:
如果中介者过多,会造成类之间的膨胀
如果相互依赖的对象过多,转换成中介者模式,会造成中介者的逻辑更加复杂