详解Java设计模式编程中的中介者模式

作者:卡奴达摩 时间:2021-09-24 02:48:54 

定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。
类型:行为类模式
类图:

详解Java设计模式编程中的中介者模式

中介者模式的结构
       中介者模式又称为调停者模式,从类图中看,共分为3部分:
 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
为什么要使用中介者模式
       一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。

详解Java设计模式编程中的中介者模式详解Java设计模式编程中的中介者模式

如果引入中介者模式,那么同事类之间的关系将变为星型结构,从图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。

详解Java设计模式编程中的中介者模式


下面给出具体的代码例子,对比通用类图增加了AbstractColleague抽象同事类和AbstractMediator抽象中介者,另外就是两个具体同事类和一个具体中介者,代码中有较多注释,相应类图也不给出了,应该不难理解的:
 
同事类族:


//抽象同事类
abstract class AbstractColleague {
 protected AbstractMediator mediator;

/**既然有中介者,那么每个具体同事必然要与中介者有联系,
  * 否则就没必要存在于 这个系统当中,这里的构造函数相当
  * 于向该系统中注册一个中介者,以取得联系
  */
 public AbstractColleague(AbstractMediator mediator) {
   this.mediator = mediator;
 }

// 在抽象同事类中添加用于与中介者取得联系(即注册)的方法
 public void setMediator(AbstractMediator mediator) {
   this.mediator = mediator;
 }
}

//具体同事A
class ColleagueA extends AbstractColleague {

//每个具体同事都通过父类构造函数与中介者取得联系
 public ColleagueA(AbstractMediator mediator) {
   super(mediator);
 }

//每个具体同事必然有自己分内的事,没必要与外界相关联
 public void self() {
   System.out.println("同事A --> 做好自己分内的事情 ...");
 }

//每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作
 public void out() {
   System.out.println("同事A --> 请求同事B做好分内工作 ...");
   super.mediator.execute("ColleagueB", "self");
 }
}

//具体同事B
class ColleagueB extends AbstractColleague {

public ColleagueB(AbstractMediator mediator) {
   super(mediator);
 }

public void self() {
   System.out.println("同事B --> 做好自己分内的事情 ...");
 }

public void out() {
   System.out.println("同事B --> 请求同事A做好分内工作 ...");
   super.mediator.execute("ColleagueA", "self");
 }
}

中介者类族:


//抽象中介者
abstract class AbstractMediator {

//中介者肯定需要保持有若干同事的联系方式
 protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();

//中介者可以动态地与某个同事建立联系
 public void addColleague(String name, AbstractColleague c) {
   this.colleagues.put(name, c);
 }  

//中介者也可以动态地撤销与某个同事的联系
 public void deleteColleague(String name) {
   this.colleagues.remove(name);
 }

//中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作
 public abstract void execute(String name, String method);  
}

//具体中介者
class Mediator extends AbstractMediator{

//中介者最重要的功能,来回奔波与各个同事之间
 public void execute(String name, String method) {

if("self".equals(method)){ //各自做好分内事
     if("ColleagueA".equals(name)) {
       ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");
       colleague.self();
     }else {
       ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");
       colleague.self();
     }
   }else { //与其他同事合作
     if("ColleagueA".equals(name)) {
       ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");
       colleague.out();
     }else {
       ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");
       colleague.out();
     }
   }
 }
}

测试类:


//测试类
public class Client {
 public static void main(String[] args) {

//创建一个中介者
   AbstractMediator mediator = new Mediator();

//创建两个同事
   ColleagueA colleagueA = new ColleagueA(mediator);
   ColleagueB colleagueB = new ColleagueB(mediator);

//中介者分别与每个同事建立联系
   mediator.addColleague("ColleagueA", colleagueA);
   mediator.addColleague("ColleagueB", colleagueB);

//同事们开始工作
   colleagueA.self();
   colleagueA.out();
   System.out.println("======================合作愉快,任务完成!\n");

colleagueB.self();
   colleagueB.out();
   System.out.println("======================合作愉快,任务完成!");
 }
}

测试结果: 


同事A --> 做好自己分内的事情 ...
同事A --> 请求同事B做好分内工作 ...
同事B --> 做好自己分内的事情 ...
======================合作愉快,任务完成!

同事B --> 做好自己分内的事情 ...
同事B --> 请求同事A做好分内工作 ...
同事A --> 做好自己分内的事情 ...
======================合作愉快,任务完成!

 
虽然以上代码中只有两个具体同事类,并且测试类中也只是创建了两个同事,但是这些我们都可以根据中介者模式的宗旨进行适当地扩展,即增加具体同事类,然后中介者就得担负更加重的任务了。为啥?我们看到上面具体中介者类Mediator中的execute()方法中现在就有一堆冗长的判断代码了。虽然可以把它分解并增加到Mediator类中的其它private方法中,但是具体的业务逻辑是少不了的。
 
所以,在解耦同事类之间的联系的同时,中介者自身也不免任务过重,因为几乎所有的业务逻辑都交代到中介者身上了,可谓是“万众期待”的一个角色了。这就是中介者模式的不足之处了 。
此外,上面这个代码例子是相当理想的了,有时候我们根本抽取不了“同事”之间的共性来形成一个AbstractColleague抽象同事类,这也大大增加了中介者模式的使用难度。  
修改:
由于上面代码实现中存在 benjielin 前辈提出的“双向关联暴露在App中”的不足之处,根据给出的改进方法2,修改上面代码,如下:
 
修改后的同事类族:
 


//抽象同事类
abstract class AbstractColleague {
 protected AbstractMediator mediator;  

//舍去在构造函数中建立起与中介者的联系
// public AbstractColleague(AbstractMediator mediator) {
//   this.mediator = mediator;
// }

// 在抽象同事类中添加用于与中介者取得联系(即注册)的方法
 public void setMediator(AbstractMediator mediator) {
   this.mediator = mediator;
 }
}

//具体同事A
class ColleagueA extends AbstractColleague {

//舍去在构造函数中建立起与中介者的联系
// public ColleagueA(AbstractMediator mediator) {
//   super(mediator);
// }

//每个具体同事必然有自己分内的事,没必要与外界相关联
 public void self() {
   System.out.println("同事A --> 做好自己分内的事情 ...");
 }

//每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作
 public void out() {
   System.out.println("同事A --> 请求同事B做好分内工作 ...");
   super.mediator.execute("ColleagueB", "self");
 }
}

//具体同事B
class ColleagueB extends AbstractColleague {
 //舍去在构造函数中建立起与中介者的联系
// public ColleagueB(AbstractMediator mediator) {
//   super(mediator);
// }

public void self() {
   System.out.println("同事B --> 做好自己分内的事情 ...");
 }

public void out() {
   System.out.println("同事B --> 请求同事A做好分内工作 ...");
   super.mediator.execute("ColleagueA", "self");
 }
}

 
修改后的中介者:


//抽象中介者
abstract class AbstractMediator {

//中介者肯定需要保持有若干同事的联系方式
 protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();

//中介者可以动态地与某个同事建立联系
 public void addColleague(String name, AbstractColleague c) {

// 在中介者这里帮助具体同事建立起于中介者的联系
   c.setMediator(this);
   this.colleagues.put(name, c);
 }  

//中介者也可以动态地撤销与某个同事的联系
 public void deleteColleague(String name) {
   this.colleagues.remove(name);
 }

//中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作
 public abstract void execute(String name, String method);  
}
//测试类
public class Client {
 public static void main(String[] args) {

//创建一个中介者
   AbstractMediator mediator = new Mediator();

//不用构造函数为具体同事注册中介者来取得联系了
//   ColleagueA colleagueA = new ColleagueA(mediator);
//   ColleagueB colleagueB = new ColleagueB(mediator);

ColleagueA colleagueA = new ColleagueA();
   ColleagueB colleagueB = new ColleagueB();

//中介者分别与每个同事建立联系
   mediator.addColleague("ColleagueA", colleagueA);
   mediator.addColleague("ColleagueB", colleagueB);

//同事们开始工作
   colleagueA.self();
   colleagueA.out();
   System.out.println("======================合作愉快,任务完成!\n");

colleagueB.self();
   colleagueB.out();
   System.out.println("======================合作愉快,任务完成!");
 }
}

  测试之后的结果与修改前一样。

标签:Java,设计模式
0
投稿

猜你喜欢

  • C#中动态数组用法实例

    2021-11-30 16:42:23
  • ionic监听android返回键实现“再按一次退出”功能

    2021-12-24 10:22:57
  • Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 实现分库分表功能

    2023-08-28 16:52:09
  • C#实现集合转换成json格式数据的方法

    2022-03-18 03:28:50
  • C语言时间函数之strftime()详解

    2023-06-26 02:42:32
  • mybaties plus selectMaps和selectList的区别说明

    2021-07-15 11:18:29
  • 浅谈Java基准性能测试之JMH

    2023-01-25 13:17:40
  • Android监听手机电话状态与发送邮件通知来电号码的方法(基于PhoneStateListene实现)

    2022-12-07 09:03:44
  • Android组件banner实现左右滑屏效果

    2023-11-01 17:54:59
  • Android编程使用LinearLayout和PullRefreshView实现上下翻页功能的方法

    2023-06-30 02:16:15
  • 互斥量mutex的简单使用(实例讲解)

    2023-09-20 21:36:50
  • Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法

    2023-12-15 01:21:32
  • 详解Spring-Boot集成Spring session并存入redis

    2021-10-13 07:48:30
  • C#中if语句使用概述

    2022-08-31 23:22:09
  • C#中使用DevExpress中的ChartControl实现极坐标图的案例详解

    2022-12-05 06:30:39
  • 浅谈java 执行jar包中的main方法

    2022-06-28 07:58:27
  • Java实现两人五子棋游戏(二) 画出棋盘

    2022-08-26 15:09:57
  • 在C#中使用Channels的完整教程

    2021-11-03 15:41:28
  • Android开源框架的SlidingFragment的使用示例

    2021-06-18 09:37:31
  • C语言函数声明以及函数原型超详细讲解示例

    2023-03-31 03:12:02
  • asp之家 软件编程 m.aspxhome.com