目 录CONTENT

文章目录

中介者模式

半糖
2024-08-28 / 0 评论 / 0 点赞 / 16 阅读 / 8717 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2024-08-28,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

名称

中介者模式(MEDIATOR)

目的

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

适用性

在下列情况下使用中介者模式 :

  • 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。

  • 一个对象引用其他很多对象并且直接与这些对象通信 ,导致难以复用该对象。

  • 想定制一个分布在多个类中的行为,而又不想生成太多的子类。

结构

中介者(Mediator):中介者定义一个接口用于与各同事(Colleague)对象通信。

具体中介者(ConcreteMediator)

  • 具体中介者通过协调各同事对象实现协作行为。

  • 了解并维护它的各个同事。

同事(Colleage):定义了一个接口,用于与中介者进行通信。通常包括一个发送消息的方法,以及一个接收消息的方法。

具体同事(ConcreteColleague):实现了同事接口,是真正参与到交互中的对象。它会将自己的消息发送给中介者,由中介者转发给其他同事对象。

协作

同事向一个中介者对象发送和接收请求。中介者在各同事间适当地转发请求以实现协作行为。

效果

优点

  1. 减少了子类。Mediator将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成Meditator的子类即可,这样各个Colleague类可被重用。

  2. 将各Colleague解耦。Mediator有利于各Colleague间的松耦合,可以独立的改变和复用各Colleague类和Mediator类,Coleague之间符合迪米特法则。

  3. 它简化了对象协议。用Mediator和各Colleague间的一对多的交互来代替多对多的交互,一对多的关系更易于理解、维护和扩展。

  4. 它对对象如何协作进行了抽象。将中介作为一个独立的概念并将其封装在一个对象中,将注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清楚一个系统中的对象是如何交互的。

  5. 提高系统的灵活性。中介者模式使得系统中的对象(同事类对象)可以独立地被复用,因为它们不再依赖于其他对象(内部引用的具体实例)的具体实现。
    打个比方:没有中介者的时候,假设有类A,它有个对象引用B是接口或者某个有子类的对象,当其他地方调用A的时候,就要确定引用B的具体实例是B1还是B2,所以这种情况类A就依赖于引用B的具体实现;当使用中介者模式后,类A不再保持有引用B,引用B放在中介者中,不用引用B的时候直接使用类A的对象,要用引用B的时候通过中介者进行调用,引用B具体使用什么实例交给中介者去判定,这样就提高了系统的灵活性(实际上是将复杂度转移到中介者了),这样做的好处一是集中了指定引用B具体实例的操作,二是简化了A的结构,使A用起来更丝滑。

缺点

  1. 它使控制集中化。中介者模式将交互的复杂性变为中介者的复杂性。因为中介者封装了协议,它可能变得比任一个Colleague都复杂,这可能使得中介者自身成为一个难于维护的庞然大物。

  2. 单点故障。由于所有的交互都通过中介者来进行,一旦中介者对象出现故障,整个系统可能会受到影响。

  3. 性能影响。中介者的引入可能会增加一些额外的性能开销,因为所有的请求都需要经过中介者来转发。

  4. 可测试性降低。中介者模式使得对象之间的交互变得更加间接,这可能会使得单元测试变得更加困难,因为需要模拟中介者的行为。

实现

  1. 忽略抽象的Mediator类。当各Colleague仅与一个Mediator一起工作时,没有必要定义一个抽象的Mediator类,Mediator类提供的抽象耦合已经使各Colleague可与不同的Mediator子类一起工作,反之亦然。

  2. Colleague—Mediator通信。当一个感兴趣的事件发生时,Colleague必须与其Mediator通信。一种实现方法是使用观察者模式,将Mediator实现为一个Observer,各Colleague作为Subject,一旦其状态改变就发送通知给Mediator。Mediator作出的响应是将状态改变的结果传播给其他的Colleague。
    另一个方法是在Mediator中定义一个特殊的通知接口,各Colleague在通信时直接调用该接口。当与Mediator通信时,Colleague将自身作为一个参数传递给Mediator,使其可以识别发送者。

应用

问题

当我们想要租房子的时候,首先去找到中介,中介再给我们找到合适的房源,这个过程中有三个角色分别是:租客、中介、房东,为什么能产生联系呢?是因为租客和房东拥有中介的联系方式,而中介又拥有租客和房东的联系方式,这就是最典型的中介模式。从结构图我们可以看出来,具体同事拥有中介的对象引用,中介拥有具体同事的引用,当具体同事之间想要通信时,具体同事对象A调用自己对象内的中介对象,中介对象再调用对应的具体同事对象B,实现A到B之间的通信。

示例

UML

代码示例

抽象中介者:中介

package com.ysj.part5.mediator.mediator;

import com.ysj.part5.mediator.colleague.Person;

/**
 * 中介者:中介
 */
public abstract class Mediator {

    /**
     * 联系某人
     * @param message
     * @param person
     */
    public abstract void constact(String message, Person person);

}

具体中介者:小王,实现中介,

package com.ysj.part5.mediator.concreteMediator;

import com.ysj.part5.mediator.colleague.Person;
import com.ysj.part5.mediator.concreteColleague.HouseOwner;
import com.ysj.part5.mediator.concreteColleague.Tenant;
import com.ysj.part5.mediator.mediator.Mediator;
import lombok.Data;

/**
 * 具体中介:小王
 */
@Data
public class XiaoWang extends Mediator {

    /**
     * 具体同事:房主
     */
    private HouseOwner houseOwner;

    /**
     * 具体同事:租客
     */
    private Tenant tenant;

    public void constact(String message, Person person) {
        if (person == houseOwner) {          //房主获取信息
            tenant.getMessage(message);
        } else {       //租客
            houseOwner.getMessage(message);
        }
    }
}

同事:人,同事类也可以不要

package com.ysj.part5.mediator.colleague;

import com.ysj.part5.mediator.mediator.Mediator;

/**
 * 同事:人
 */
public abstract class Person {

    /**
     * 姓名
     */
    protected String name;

    /**
     * 中介者:中介
     */
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }

}

具体同事:房主

package com.ysj.part5.mediator.concreteColleague;

import com.ysj.part5.mediator.colleague.Person;
import com.ysj.part5.mediator.mediator.Mediator;

/**
 * 具体同事类:房主
 */
public class HouseOwner extends Person {

    public HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }

    /**
     * @param message
     * @return void
     * @desc 与中介者联系
     */
    public void constact(String message) {
        mediator.constact(message, this);
    }

    /**
     * @param message
     * @return void
     * @desc 获取信息
     */
    public void getMessage(String message) {
        System.out.println("房主[" + name + "]获得信息:" + message);
    }
}

具体同事:租客

package com.ysj.part5.mediator.concreteColleague;

import com.ysj.part5.mediator.colleague.Person;
import com.ysj.part5.mediator.mediator.Mediator;

/**
 * 具体同事:租客
 */
public class Tenant extends Person {

    public Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

    /**
     * @desc 与中介者联系
     * @param message
     * @return void
     */
    public void constact(String message){
        mediator.constact(message, this);
    }

    /**
     * @desc 获取信息
     * @param message
     * @return void
     */
    public void getMessage(String message){
        System.out.println("租房者[" + name +"]获得信息:" + message);
    }
}

客户端:客户端

package com.ysj.part5.mediator;

import com.ysj.part5.mediator.concreteColleague.HouseOwner;
import com.ysj.part5.mediator.concreteColleague.Tenant;
import com.ysj.part5.mediator.concreteMediator.XiaoWang;

/**
 * 中介者模式
 * 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
 */
public class Client {
    public static void main(String[] args) {
        //一个房主、一个租房者、一个中介机构
        XiaoWang mediator = new XiaoWang();

        //房主和租房者只需要知道中介机构即可
        HouseOwner houseOwner = new HouseOwner("张三", mediator);
        Tenant tenant = new Tenant("李四", mediator);

        //中介结构要知道房主和租房者
        mediator.setHouseOwner(houseOwner);
        mediator.setTenant(tenant);

        //租客和房客调用“与中介者联系”的方法,中介者将对方的话进行转接
        tenant.constact("听说你那里有三室的房主出租.....");
        houseOwner.constact("是的!请问你需要租吗?");
    }
}

已知应用

Java Swing/AWT

事件分发模型:Java Swing/AWT 使用中介者模式来处理事件分发,EventQueue 作为中介者,负责接收和分发事件给相应的组件。

Spring Framework

Spring MVC DispatcherServlet:Spring MVC 中的 DispatcherServlet 作为中介者,负责接收 HTTP 请求并分发给相应的控制器。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区