设计模式 - 中介者模式

970 阅读7分钟

✨作者:猫十二懿

❤️‍🔥账号:CSDN掘金个人博客Github

🎉公众号:猫十二懿

中介者模式

1、中介者模式介绍

中介者模式(Mediator Pattern)是一种行为设计模式,==用一个中介对象来封装一系列的对象交互==。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

它用于减少对象之间的直接通信,通过引入一个中介者对象来促进对象之间的松耦合。中介者模式可以帮助组织和管理复杂的交互逻辑,使得对象之间的交互更加简单和可维护。

在中介者模式中,多个对象之间的通信不再直接发生,而是通过中介者进行。中介者对象担当了对象之间的调度者和协调者的角色,它负责接收对象之间的通信请求,并将其转发给合适的接收者对象。

1.1 中介者模式基本实现

中介者模式结构图

image-20230522150506373

中介者模式的主要参与者包括以下几个角色:

  1. Colleague叫作抽象同事类
  2. ConcreteColleague是具体同事类,每个具体同事只知道自己的行为,而不了解其他同事类的情况,但他们却都认识中介者对象
  3. Mediator是抽象中介者,定义了同事对象到中介者对象的接口
  4. ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令

Colleague类:抽象同事类

/**
 * @author Shier
 * CreateTime 2023/5/22 15:08
 */
public abstract class Colleague {
    protected Mediator mediator;

    /**
     * 获取中介者对象
     * @param mediator
     */
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
}

ConcreteColleague1和ConcreteColleague2等各种同事对象:

/**
 * @author Shier
 * CreateTime 2023/5/22 15:09
 */
public class ConcreteColleague1 extends Colleague {
    /**
     * 获取中介者对象
     *
     * @param mediator
     */
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

    /**
     * 发送消息
     * @param message
     */
    public void send(String message) {
        this.mediator.send(message,this);
    }

    /**
     * 接受消息
     * @param message
     */
    public void notify(String message) {
        System.out.println("同事1收到消息 " + message);
    }
}


public class ConcreteColleague2 extends Colleague{
    /**
     * 获取中介者对象
     *
     * @param mediator
     */
    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }

    /**
     * 发送消息
     * @param message
     */
    public void send(String message) {
        this.mediator.send(message,this);
    }

    /**
     * 接受消息
     * @param message
     */
    public void notify(String message) {
        System.out.println("同事2收到消息 " + message);
    }
}

Mediator类:抽象中介者类

/**
 * @author Shier
 * CreateTime 2023/5/22 15:13
 * 抽象中介者类
 */
public abstract class Mediator {
    /**
     * 发送消息的抽象方法,得到同事对象和消息
     * @param message
     * @param colleague
     */
    public abstract void send(String message, Colleague colleague);
}

ConcreteMediator类:具体中介者类。

/**
 * @author Shier
 * CreateTime 2023/5/22 15:15
 * 具体中介者类
 */
public class ConcreteMediator extends Mediator {

    /**
     * 两个同事属性
     */
    private ConcreteColleague1 colleague1;
    private ConcreteColleague2 colleague2;

    /**
     * 知道具体同事的对象
     *
     * @param colleague1
     */
    public void setColleague1(ConcreteColleague1 colleague1) {
        this.colleague1 = colleague1;
    }

    public void setColleague2(ConcreteColleague2 colleague2) {
        this.colleague2 = colleague2;
    }

    /**
     * 重写发送消息方法,根据不同具体同事对象做出判断通知其他同事
     * @param message
     * @param colleague
     */
    @Override
    public void send(String message, Colleague colleague) {
        if (colleague == colleague1) {
            colleague2.notify(message);
        } else {
            colleague1.notify(message);
        }
    }
}

客户端:

public class MediaClient {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();

        // 两个具体同事都认识中介者
        ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
        ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
        // 中介者认识两个同事
        mediator.setColleague1(colleague1);
        mediator.setColleague2(colleague2);

        // 同事之间进行交流
        colleague1.send("你今晚吃饭了吗?");
        colleague2.send("我今晚还没有吃饭呢");
    }
}

输出结果:

image-20230522153403328

由于有了Mediator,使得ConcreteColleague1和ConcreteColleague2在发送消息和接收信息时其实是通过中介者来完成的,这就减少了它们之间的耦合。

2、具体例子说明

例子背景说明:全世界都是通过联合国组织进行交流各国之间的事务,不同国家之间都存在在不同的利益等关系,如果没有联合国那么各个国家之间的关联就会变得紧耦合。

例子:需求是美国和伊拉克之间的对话都是通过联合国安理会作为中介来完成。

例子说明:在美国和伊拉克之间存在紧张的政治关系和潜在的冲突,彼此间的直接对话往往困难且具有挑战性。为了避免冲突升级和促进和平解决,双方同意将对话的中介角色委托给联合国安全理事会。通过联合国安理会作为中介者,可以提供一个中立、公正的平台,促进双方之间的交流和协商,以实现持久和平的解决方案。中介者的介入有助于降低紧张局势,增加对话的效果和可行性。

2.1 中介者模式 - 联合国安理会

程序结构图:

image-20230522153246192

国家类:相当于Colleague类。

/**
 * @author Shier
 * CreateTime 2023/5/22 15:34
 * 国家类
 */
public abstract class Country {
    protected UnitedNations unitedNations;

    /**
     * 得到安理会中介者
     * @param unitedNations
     */
    public Country(UnitedNations unitedNations) {
        this.unitedNations = unitedNations;
    }
}

美国类:相当于ConcreteColleague1类。

/**
 * @author Shier
 * CreateTime 2023/5/22 15:36
 * 美国类
 */
public class USA extends Country {
    /**
     * 得到安理会中介者
     *
     * @param unitedNations
     */
    public USA(UnitedNations unitedNations) {
        super(unitedNations);
    }

    /**
     * 美国发布消息
     *
     * @param message
     */
    public void declare(String message) {
        this.unitedNations.declare(message, this);
    }

    /**
     * 美国接受其他国家信息
     * @param message
     */
    public void getMessage(String message) {
        System.out.println("美国收到消息:" + message);
    }
}

伊拉克类:相当于ConcreteColleague2类

/**
 * @author Shier
 * CreateTime 2023/5/22 15:36
 * 伊拉克类
 */
public class Iraq extends Country {
    /**
     * 得到安理会中介者
     *
     * @param unitedNations
     */
    public Iraq(UnitedNations unitedNations) {
        super(unitedNations);
    }

    /**
     * 伊拉克发布消息
     *
     * @param message
     */
    public void declare(String message) {
        this.unitedNations.declare(message, this);
    }

    /**
     * 伊拉克接受其他国家信息
     * @param message
     */
    public void getMessage(String message) {
        System.out.println("伊拉克收到消息:" + message);
    }
}

联合国机构类:相当于Mediator类。

/**
 * @author Shier
 * CreateTime 2023/5/22 15:40
 * 中介者
 */
public abstract class UnitedNations {
    public abstract void declare(String message,Country country);
}

联合国安理会:相当于ConcreteMediator类。

/**
 * @author Shier
 * CreateTime 2023/5/22 15:42
 */
public class UnitedNationsSecurityCouncil extends UnitedNations {
    private USA usa;
    private Iraq iraq;

    /**
     * 联合国安理会了解所有国家,所有拥有所有国家的对象属性
     *
     * @param usa
     */
    public void setUsa(USA usa) {
        this.usa = usa;
    }

    public void setIraq(Iraq iraq) {
        this.iraq = iraq;
    }

    /**
     * 对象间的通信
     * @param message
     * @param country
     */
    @Override
    public void declare(String message, Country country) {
        if (country == this.usa) {
            iraq.getMessage(message);
        } else if (country == this.iraq){
            usa.getMessage(message);
        }
    }
}

客户端调用:

/**
 * @author Shier
 * CreateTime 2023/5/22 15:44
 */
public class CountryClient {
    public static void main(String[] args) {
        UnitedNationsSecurityCouncil council = new UnitedNationsSecurityCouncil();
        // 各个国家知道安理会存在
        USA usa = new USA(council);
        Iraq iraq = new Iraq(council);

        // 联合国安理会知道每个国家存在
        council.setUsa(usa);
        council.setIraq(iraq);

        usa.declare("不准研制核武器,否则将对你发起战争");
        iraq.declare("我并没有研制核武器,但你不要威胁我");
    }
}

结果:

image-20230522160021099

以上的程序除了类名不一样,其他基本都和中介者模式的基本实现的程序一样

3、中介者模式总结

中介者模式的优点包括:

  1. 减少了对象之间的直接耦合:通过引入中介者对象,各个对象之间不再直接通信,减少了彼此之间的依赖关系,提高了系统的灵活性和可扩展性。
  2. 简化对象之间的交互:中介者模式将对象之间的交互逻辑集中在一个对象中,使得交互变得更加简单和可维护,提高了代码的可读性。
  3. 提高代码的可维护性:通过将复杂的交互逻辑放在中介者对象中,使得代码更加集中和可维护,便于后续的修改和扩展。

中介者模式的缺点包括:

  1. 中介者对象的职责较多:中介者对象通常负责协调多个对象之间的通信,可能会导致中介者对象的职责变得复杂,难以维护和扩展。
  2. 增加了系统的复杂性:引入中介者对象后,系统中会多出一个新的对象,增加了系统的复杂性,特别是当交互逻辑变得复杂时。

适用场景:

  1. 当对象之间的通信复杂且难以维护时,可以考虑使用中介者模式来简化对象之间的交互。
  2. 当系统中存在多个对象之间的交互逻辑,并且这些交互逻辑需要集中管理时,可以使用中介者模式来将交互逻辑集中在中介者对象中。
  3. 当系统中的对象之间的关系呈现网状结构时,可以考虑使用中介者模式来简化对象之间的通信和管理。
  4. 当希望通过引入中介者对象来降低对象之间的耦合性,提高系统的灵活性和可扩展性时,可以使用中介者模式。

中介者模式在图形用户界面(GUI)开发、多人协作系统、企业应用中的分布式系统等场景下得到广泛应用。