设计模式之【中介者模式】,多对多关系降级为一对多关系的利器

设计模式之【中介者模式】,多对多关系降级为一对多关系的利器中介者模式 MediatorPatt 又称为调节者模式或调停者模式

大家好,欢迎来到IT知识分享网。

全网最全最细的【设计模式】总目录,收藏起来慢慢啃,看完不懂砍我

一、什么是中介者模式

中介者模式(Mediator Pattern)又称为调节者模式或调停者模式。用一个中介对象封装一系列的对象交互,中介者使各对象不需要显式的相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互,属于行为型模式。

中介者模式的核心思想是,通过中介者解耦系统各层次对象的直接耦合,层次对象的对外依赖通信统统交由中介者转发。

1、中介者模式的优势

2、中介者模式的缺点

中介者模式中将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。

3、中介者模式的应用场景

若系统各层次对象之间存在大量的关联关系,即层次对象呈复杂的网状结构,如果直接让它们紧耦合通信,会造成系统结构变得异常复杂,且其中某个层次对象发生改变,则与其紧耦合的相应层次对象也需要进行修改,系统很难进行维护。而通过为该系统增加一个中介者层次对象,让其他各层次需对外通信的行为统统交由中介者进行转发,系统呈现以中介者为中心进行通讯的星型结构,系统的复杂性大大降低。

简单的说就是多个类相互耦合,形成了网状结构,则考虑使用中介者模式进行优化。总结中介者模式适用于以下场景:

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解;
  • 交互的公共行为,如果需要改变行为则可以增加新的中介者类。

4、中介者模式的四大角色

在这里插入图片描述
中介者模式包含以下主要角色:

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
    -具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

5、观察者模式和中介模式的区别

观察者模式有多种实现方式。虽然经典的实现方式没法彻底解耦观察者和被观察者,观察者需要注册到被观察者中,被观察者状态更新需要调用观察者的 update() 方法。但是,在跨进程的实现方式中,我们可以利用消息队列实现彻底解耦,观察者和被观察者都只需要跟消息队列交互,观察者完全不知道被观察者的存在,被观察者也完全不知道观察者的存在。

中介模式也是为了解耦对象之间的交互,所有的参与者都只与中介进行交互。而观察者模式中的消息队列,就有点类似中介模式中的“中介”,观察者模式的中观察者和被观察者,就有点类似中介模式中的“参与者”。

在观察者模式中,尽管一个参与者既可以是观察者,同时也可以是被观察者,但是,大部分情况下,交互关系往往都是单向的,一个参与者要么是观察者,要么是被观察者,不会兼具两种身份。也就是说,在观察者模式的应用场景中,参与者之间的交互关系比较有条理。

而中介模式正好相反。只有当参与者之间的交互关系错综复杂,维护成本很高的时候,我们才考虑使用中介模式。毕竟,中介模式的应用会带来一定的副作用,它有可能会产生大而复杂的上帝类。除此之外,如果一个参与者状态的改变,其他参与者执行的操作有一定先后顺序的要求,这个时候,中介模式就可以利用中介类,通过先后调用不同参与者的方法,来实现顺序的控制,而观察者模式是无法实现这样的顺序要求的。

二、实例

1、中介者模式的一般写法

// 抽象中介者 public abstract class Mediator { 
     protected ConcreteColleagueA colleagueA; protected ConcreteColleagueB colleagueB; public void setColleageA(ConcreteColleagueA colleague) { 
     this.colleagueA = colleague; } public void setColleageB(ConcreteColleagueB colleague) { 
     this.colleagueB = colleague; } // 中介者业务逻辑 public abstract void transferA(); public abstract void transferB(); } // 具体中介者 public class ConcreteMediator extends Mediator { 
     @Override public void transferA() { 
     // 协调行为:A 转发到 B this.colleagueB.selfMethodB(); } @Override public void transferB() { 
     // 协调行为:B 转发到 A this.colleagueA.selfMethodA(); } } 
// 抽象同事类 public abstract class Colleague { 
     protected Mediator mediator; public Colleague(Mediator mediator) { 
     this.mediator = mediator; } } // 具体同事类 public class ConcreteColleagueA extends Colleague { 
     public ConcreteColleagueA(Mediator mediator) { 
     super(mediator); this.mediator.setColleageA(this); } // 自有方法:self-Method public void selfMethodA() { 
     // 处理自己的逻辑 System.out.println(String.format("%s:self-Method", this.getClass().getSimpleName())); } // 依赖方法:dep-Method public void depMethodA() { 
     // 处理自己的逻辑 System.out.println(String.format("%s:depMethod: delegate to Mediator", this.getClass().getSimpleName())); // 无法处理的业务逻辑委托给中介者处理 this.mediator.transferA(); } } // 具体同事类 public class ConcreteColleagueB extends Colleague { 
     public ConcreteColleagueB(Mediator mediator) { 
     super(mediator); this.mediator.setColleageB(this); } // 自有方法:self-Method public void selfMethodB() { 
     // 处理自己的逻辑 System.out.println(String.format("%s:self-Method", this.getClass().getSimpleName())); } // 依赖方法:dep-Method public void depMethodB() { 
     // 处理自己的逻辑 System.out.println(String.format("%s:depMethod: delegate to Mediator", this.getClass().getSimpleName())); // 无法处理的业务逻辑委托给中介者处理 this.mediator.transferB(); } } 
// 测试类 public class Test { 
     public static void main(String[] args) { 
     Mediator mediator = new ConcreteMediator(); ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator); ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator); colleagueA.depMethodA(); System.out.println("-------------------------"); colleagueB.depMethodB(); } } 

2、租房中介案例

现在租房基本都是通过房屋中介,房主将房屋托管给房屋中介,而租房者从房屋中介获取房屋信息。房屋中介充当租房者与房屋所有者之间的中介者。

 //抽象同事类 public abstract class Person { 
     protected String name; protected Mediator mediator; public Person(String name,Mediator mediator){ 
     this.name = name; this.mediator = mediator; } } //具体同事类 房屋拥有者 public class HouseOwner extends Person { 
     public HouseOwner(String name, Mediator mediator) { 
     super(name, mediator); } //与中介者联系 public void constact(String message){ 
     mediator.constact(message, this); } //获取信息 public void getMessage(String message){ 
     System.out.println("房主" + name +"获取到的信息:" + message); } } //具体同事类 承租人 public class Tenant extends Person { 
     public Tenant(String name, Mediator mediator) { 
     super(name, mediator); } //与中介者联系 public void constact(String message){ 
     mediator.constact(message, this); } //获取信息 public void getMessage(String message){ 
     System.out.println("租房者" + name +"获取到的信息:" + message); } } 
//抽象中介者 public abstract class Mediator { 
     //申明一个联络方法 public abstract void constact(String message,Person person); } //中介机构 public class MediatorStructure extends Mediator { 
     //首先中介结构必须知道所有房主和租房者的信息 private HouseOwner houseOwner; private Tenant tenant; public HouseOwner getHouseOwner() { 
     return houseOwner; } public void setHouseOwner(HouseOwner houseOwner) { 
     this.houseOwner = houseOwner; } public Tenant getTenant() { 
     return tenant; } public void setTenant(Tenant tenant) { 
     this.tenant = tenant; } public void constact(String message, Person person) { 
     if (person == houseOwner) { 
     //如果是房主,则租房者获得信息 tenant.getMessage(message); } else { 
     //反正则是房主获得信息 houseOwner.getMessage(message); } } } 
//测试类 public class Client { 
     public static void main(String[] args) { 
     //一个房主、一个租房者、一个中介机构 MediatorStructure mediator = new MediatorStructure(); //房主和租房者只需要知道中介机构即可 HouseOwner houseOwner = new HouseOwner("张三", mediator); Tenant tenant = new Tenant("李四", mediator); //中介结构要知道房主和租房者 mediator.setHouseOwner(houseOwner); mediator.setTenant(tenant); tenant.constact("需要租三室的房子"); houseOwner.constact("我这有三室的房子,你需要租吗?"); } } 

3、智能家具案例

智能家居包括各种智能设备,闹钟、咖啡机、电视、窗帘等,主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程未:闹钟响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放。

//同事抽象类 public abstract class Colleague { 
     private Mediator mediator; public String name; public Colleague(Mediator mediator, String name) { 
     this.mediator = mediator; this.name = name; } public Mediator GetMediator() { 
     return this.mediator; } public abstract void SendMessage(int stateChange); } //具体的同事类-闹钟 public class Alarm extends Colleague { 
     //构造器 public Alarm(Mediator mediator, String name) { 
     super(mediator, name); //在创建Alarm 同事对象时,将自己放入到ConcreteMediator 对象中[集合] mediator.Register(name, this); } public void SendAlarm(int stateChange) { 
     SendMessage(stateChange); } @Override public void SendMessage(int stateChange) { 
     //调用的中介者对象的getMessage this.GetMediator().GetMessage(stateChange, this.name); } } // 具体同事类-咖啡机 public class CoffeeMachine extends Colleague { 
     public CoffeeMachine(Mediator mediator, String name) { 
     super(mediator, name); mediator.Register(name, this); } @Override public void SendMessage(int stateChange) { 
     this.GetMediator().GetMessage(stateChange, this.name); } public void StartCoffee() { 
     System.out.println("It's time to startcoffee!"); } public void FinishCoffee() { 
     System.out.println("After 5 minutes!"); System.out.println("Coffee is ok!"); SendMessage(0); } } // 具体同事类-窗帘 public class Curtains extends Colleague { 
     public Curtains(Mediator mediator, String name) { 
     super(mediator, name); mediator.Register(name, this); } @Override public void SendMessage(int stateChange) { 
     this.GetMediator().GetMessage(stateChange, this.name); } public void UpCurtains() { 
     System.out.println("I am holding Up Curtains!"); } } // 具体同事类-电视 public class TV extends Colleague { 
     public TV(Mediator mediator, String name) { 
     super(mediator, name); mediator.Register(name, this); } @Override public void SendMessage(int stateChange) { 
     this.GetMediator().GetMessage(stateChange, this.name); } public void StartTv() { 
     System.out.println("It's time to StartTv!"); } public void StopTv() { 
     System.out.println("StopTv!"); } } 
// 抽象中介 public abstract class Mediator { 
     //将给中介者对象,加入到集合中 public abstract void Register(String colleagueName, Colleague colleague); //接收消息, 具体的同事对象发出 public abstract void GetMessage(int stateChange, String colleagueName); public abstract void SendMessage(); } 
//具体的中介者类 public class ConcreteMediator extends Mediator { 
     //集合,放入所有的同事对象 private HashMap<String, Colleague> colleagueMap; private HashMap<String, String> interMap; public ConcreteMediator() { 
     colleagueMap = new HashMap<String, Colleague>(); interMap = new HashMap<String, String>(); } @Override public void Register(String colleagueName, Colleague colleague) { 
     colleagueMap.put(colleagueName, colleague); if (colleague instanceof Alarm) { 
     interMap.put("Alarm", colleagueName); } else if (colleague instanceof CoffeeMachine) { 
     interMap.put("CoffeeMachine", colleagueName); } else if (colleague instanceof TV) { 
     interMap.put("TV", colleagueName); } else if (colleague instanceof Curtains) { 
     interMap.put("Curtains", colleagueName); } } //具体中介者的核心方法 //1. 根据得到消息,完成对应任务 //2. 中介者在这个方法,协调各个具体的同事对象,完成任务 @Override public void GetMessage(int stateChange, String colleagueName) { 
     //处理闹钟发出的消息 if (colleagueMap.get(colleagueName) instanceof Alarm) { 
     if (stateChange == 0) { 
     ((CoffeeMachine) (colleagueMap.get(interMap .get("CoffeeMachine")))).StartCoffee(); ((TV) (colleagueMap.get(interMap.get("TV")))).StartTv(); } else if (stateChange == 1) { 
     ((TV) (colleagueMap.get(interMap.get("TV")))).StopTv(); } } else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) { 
     ((Curtains) (colleagueMap.get(interMap.get("Curtains")))) .UpCurtains(); } else if (colleagueMap.get(colleagueName) instanceof TV) { 
    //如果TV发现消息 } else if (colleagueMap.get(colleagueName) instanceof Curtains) { 
     //如果是以窗帘发出的消息,这里处理... } } @Override public void SendMessage() { 
     } } 
// 测试类 public class ClientTest { 
     public static void main(String[] args) { 
     //创建一个中介者对象 Mediator mediator = new ConcreteMediator(); //创建Alarm 并且加入到 ConcreteMediator 对象的HashMap Alarm alarm = new Alarm(mediator, "alarm"); //创建了CoffeeMachine 对象,并 且加入到 ConcreteMediator 对象的HashMap CoffeeMachine coffeeMachine = new CoffeeMachine(mediator, "coffeeMachine"); //创建 Curtains , 并 且加入到 ConcreteMediator 对象的HashMap Curtains curtains = new Curtains(mediator, "curtains"); TV tV = new TV(mediator, "TV"); //让闹钟发出消息 alarm.SendAlarm(0); coffeeMachine.FinishCoffee(); alarm.SendAlarm(1); } } 

三、源码中的中介者模式

1、Timer

private void sched(TimerTask task, long time, long period) { 
     if (time < 0) throw new IllegalArgumentException("Illegal execution time."); // Constrain value of period sufficiently to prevent numeric // overflow while still being effectively infinitely large. if (Math.abs(period) > (Long.MAX_VALUE >> 1)) period >>= 1; synchronized(queue) { 
     if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { 
     if (task.state != TimerTask.VIRGIN) throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time; task.period = period; task.state = TimerTask.SCHEDULED; } queue.add(task); if (queue.getMin() == task) queue.notify(); } } 

我们发现,最终会将任务加入到一个queue队列中顺序执行。我们把这个队列中的所有对象称为“同事”。同事之间通信都是通过Timer进行协调的,Timer就承担了中介者的角色。


免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120823.html

(0)
上一篇 2025-10-27 11:45
下一篇 2025-10-27 12:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信