【再谈设计模式】中介者模式 - 协调对象间交互的枢纽

简介: 中介者模式定义了一个中介对象来封装一组对象之间的交互方式。中介者使得各对象之间不需要显式地相互引用,从而降低了它们之间的耦合度。它通过将对象之间的交互逻辑集中到中介者对象中,使得系统的结构更加清晰,易于维护和扩展。

{62146138-A03B-4CC4-B3C8-328068F5A4A8}.png

一、引言

在复杂的软件系统中,对象之间的交互往往错综复杂。当众多对象相互依赖、频繁通信时,系统的耦合度会急剧上升,导致代码难以维护、扩展和理解。就像在一个大型社交聚会中,如果每个人都直接与其他人交流,场面会变得混乱不堪。中介者模式的出现,就如同一位社交组织者,它简化了对象之间的交互关系,使系统更加有序和易于管理。

二、定义与描述

中介者模式定义了一个中介对象来封装一组对象之间的交互方式。中介者使得各对象之间不需要显式地相互引用,从而降低了它们之间的耦合度。它通过将对象之间的交互逻辑集中到中介者对象中,使得系统的结构更加清晰,易于维护和扩展。

三、抽象背景

在面向对象的软件设计中,随着系统功能的不断增加,对象之间的交互逻辑会变得越来越复杂。例如,在一个图形用户界面(GUI)系统中,多个按钮、文本框和菜单之间可能存在复杂的交互关系,如点击按钮可能会影响文本框的显示内容,菜单的选择可能会改变按钮的可用性等。如果不采用合适的设计模式,这些对象之间的直接交互会导致代码的高度耦合,任何一个对象的改变都可能影响到其他多个对象。

四、适用场景与现实问题解决

(一)适用场景

GUI组件交互

在桌面应用程序的GUI开发中,多个控件(如按钮、文本框、下拉菜单等)之间存在复杂的交互逻辑。中介者模式可以将这些控件之间的交互逻辑封装在中介者对象中,使得每个控件只需与中介者对象交互,而不需要知道其他控件的具体情况。
{C471510D-4A27-45BE-B8BD-2EAC73C24887}.png

游戏开发中的角色交互

在多人游戏中,不同角色之间可能存在各种交互,如交易、战斗、组队等。使用中介者模式可以将角色之间的交互逻辑集中管理,便于游戏逻辑的维护和扩展。

分布式系统中的节点通信

在分布式系统中,多个节点需要相互通信以协调工作。中介者模式可以通过一个中介节点来管理其他节点之间的通信,简化通信协议和逻辑。

(二)现实问题解决

降低耦合度

传统的对象间直接交互会导致对象之间紧密耦合,一个对象的变化可能需要修改多个与之相关的对象。中介者模式将对象间的交互转移到中介者对象中,使得对象之间的依赖关系减少。例如,在一个电商系统中,订单处理、库存管理和用户通知等模块之间存在复杂的交互。如果采用中介者模式,这些模块只需与中介者交互,当订单处理模块发生变化时,不会直接影响库存管理和用户通知模块,只需要调整中介者中的相关逻辑即可。

简化复杂交互逻辑

    当多个对象之间存在多对多的交互关系时,交互逻辑会变得非常复杂。中介者模式将这些复杂的交互逻辑集中到中介者对象中,使得系统的整体逻辑更加清晰。例如,在一个航空订票系统中,乘客、航班、航空公司等多个对象之间存在复杂的交互关系,如航班变更时需要通知乘客和航空公司进行相应的调整。通过中介者模式,可以将这些交互逻辑集中到一个订票中介者对象中,便于管理和维护。

{862AD808-ABF3-431A-9C62-54A73AA5EFAF}.png

五、中介者模式的现实生活的例子

机场塔台

在机场中,飞机(多个对象)之间不能直接相互指挥飞行路径等操作,而是通过机场塔台(中介者)来协调。塔台接收来自各个飞机的请求(如起飞、降落、等待等),并根据整体的机场运行情况(如跑道占用、天气状况等)向飞机发出指令,以确保机场的安全和高效运行。
{F9CC3E72-7DD2-4332-AAE6-563527FCB9A8}.png

房屋中介

在房地产交易中,卖家和买家(多个对象)之间通常不会直接协商房屋交易的所有细节。房屋中介(中介者)作为中间角色,收集卖家的房屋信息和价格期望,以及买家的购房需求和预算,然后协调双方进行看房、议价等活动,最终促成交易。

六、初衷与问题解决

初衷

中介者模式的初衷是为了降低对象之间的耦合度,提高系统的可维护性和可扩展性。当系统中的对象数量增加,对象之间的交互关系变得复杂时,通过引入中介者对象,可以将复杂的多对多交互关系简化为对象与中介者之间的一对多关系。

问题解决

如前面所述,它解决了对象之间的高度耦合问题,使得系统在面临需求变更或功能扩展时,不需要对大量的对象进行修改。同时,也简化了复杂的交互逻辑,提高了系统的整体清晰度,便于开发人员理解和维护系统。

七、代码示例

类图:

{E3B0BD57-3A97-4919-B797-C8BC2E2AE6D5}.png

(一)Java示例

// 中介者接口interface Mediator {    void notify(Colleague colleague);
}// 同事类抽象类abstract class Colleague {    protected Mediator mediator;    public Colleague(Mediator mediator) {        this.mediator = mediator;
    }    abstract void receive();    abstract void send();
}// 具体同事类Aclass ConcreteColleagueA extends Colleague {    public ConcreteColleagueA(Mediator mediator) {        super(mediator);
    }    @Override
    void receive() {
   
        System.out.println("ConcreteColleagueA received a message");
    }    @Override
    void send() {
   
        System.out.println("ConcreteColleagueA sends a message");
        mediator.notify(this);
    }
}// 具体同事类Bclass ConcreteColleagueB extends Colleague {    public ConcreteColleagueB(Mediator mediator) {        super(mediator);
    }    @Override
    void receive() {
   
        System.out.println("ConcreteColleagueB received a message");
    }    @Override
    void send() {
   
        System.out.println("ConcreteColleagueB sends a message");
        mediator.notify(this);
    }
}// 具体中介者类class ConcreteMediator implements Mediator {    private ConcreteColleagueA colleagueA;    private ConcreteColleagueB colleagueB;    public void setColleagueA(ConcreteColleagueA colleagueA) {        this.colleagueA = colleagueA;
    }    public void setColleagueB(ConcreteColleagueB colleagueB) {
           this.colleagueB = colleagueB;
    }    @Override
    public void notify(Colleague colleague) {
           if (colleague == colleagueA) {
   
            colleagueB.receive();
        } else {
   
            colleagueA.receive();
        }
    }
}// 测试类public class MediatorPatternJava {    public static void main(String[] args) {        ConcreteMediator mediator = new ConcreteMediator();        ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);        ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
        mediator.setColleagueA(colleagueA);
        mediator.setColleagueB(colleagueB);
        colleagueA.send();
        colleagueB.send();
    }
}

流程图:
{CA8AD525-20B3-4582-889C-BA5DBECA0978}.png

时序图:
{33180A37-FC57-4172-9EAF-6052814CFB13}.png

(二)C++示例

#include <iostream>// 中介者类class Mediator {public:    virtual void notify(class Colleague *colleague) = 0;
};// 同事类抽象类class Colleague {protected:
    Mediator *mediator;public:    Colleague(Mediator *m) : mediator(m) {
   }    virtual void receive() = 0;    virtual void send() = 0;
};// 具体同事类Aclass ConcreteColleagueA : public Colleague {public:    ConcreteColleagueA(Mediator *m) : Colleague(m) {}    void receive() override {
   
        std::cout << "ConcreteColleagueA received a message" << std::endl;
    }    void send() override {
   
        std::cout << "ConcreteColleagueA sends a message" << std::endl;
        mediator->notify(this);
    }
};// 具体同事类Bclass ConcreteColleagueB : public Colleague {public:    ConcreteColleagueB(Mediator *m) : Colleague(m) {}    void receive() override {
   
        std::cout << "ConcreteColleagueB received a message" << std::endl;
    }    void send() override {
   
        std::cout << "ConcreteColleagueB sends a message" << std::endl;
        mediator->notify(this);
    }
};// 具体中介者类class ConcreteMediator : public Mediator {private:
    ConcreteColleagueA *colleagueA;
    ConcreteColleagueB *colleagueB;public:    void setColleagueA(ConcreteColleagueA *a) {
   
        colleagueA = a;
    }    void setColleagueB(ConcreteColleagueB *b) {
   
        colleagueB = b;
    }    void notify(Colleague *colleague) override {
           if (colleague == colleagueA) {
   
            colleagueB->receive();
        } else {
   
            colleagueA->receive();
        }
    }
};// 测试函数int main() {
   
    ConcreteMediator mediator;    ConcreteColleagueA colleagueA(&mediator);    ConcreteColleagueB colleagueB(&mediator);
    mediator.setColleagueA(&colleagueA);
    mediator.setColleagueB(&colleagueB);
    colleagueA.send();
    colleagueB.send();    return 0;
}

(三)Python示例

# 中介者类class Mediator:    def notify(self, colleague):        pass# 同事类抽象类class Colleague:    def __init__(self, mediator):
        self.mediator = mediator    def receive(self):        pass

    def send(self):        pass# 具体同事类Aclass ConcreteColleagueA(Colleague):    def receive(self):        print("ConcreteColleagueA received a message")    def send(self):        print("ConcreteColleagueA sends a message")
        self.mediator.notify(self)# 具体同事类Bclass ConcreteColleagueB(Colleague):    def receive(self):        print("ConcreteColleagueB received a message")    def send(self):        print("ConcreteColleagueB sends a message")
        self.mediator.notify(self)# 具体中介者类class ConcreteMediator(Mediator):    def __init__(self):
        self.colleagueA = None
        self.colleagueB = None

    def set_colleagueA(self, colleagueA):
        self.colleagueA = colleagueA    def set_colleagueB(self, colleagueB):
        self.colleagueB = colleagueB    def notify(self, colleague):        if colleague == self.colleagueA:
            self.colleagueB.receive()        else:
            self.colleagueA.receive()# 测试代码if __name__ == "__main__":
    mediator = ConcreteMediator()
    colleagueA = ConcreteColleagueA(mediator)
    colleagueB = ConcreteColleagueB(mediator)
    mediator.set_colleagueA(colleagueA)
    mediator.set_colleagueB(colleagueB)
    colleagueA.send()
    colleagueB.send()

(四)Go示例

package mainimport (    "fmt")// 中介者接口type Mediator interface {
   
    notify(colleague Colleague)
}// 同事类接口type Colleague interface {
   
    receive()
    send()
}// 具体同事类Atype ConcreteColleagueA struct {
   
    mediator Mediator
}func (c *ConcreteColleagueA) receive() {
   
    fmt.Println("ConcreteColleagueA received a message")
}func (c *ConcreteColleagueA) send() {
   
    fmt.Println("ConcreteColleagueA sends a message")
    c.mediator.notify(c)
}// 具体同事类Btype ConcreteColleagueB struct {
   
    mediator Mediator
}func (c *ConcreteColleagueB) receive() {
   
    fmt.Println("ConcreteColleagueB received a message")
}func (c *ConcreteColleagueB) send() {
   
    fmt.Println("ConcreteColleagueB sends a message")
    c.mediator.notify(c)
}// 具体中介者类type ConcreteMediator struct {
   
    colleagueA *ConcreteColleagueA
    colleagueB *ConcreteColleagueB
}func (m *ConcreteMediator) notify(colleague Colleague) {
       if _, ok := colleague.(*ConcreteColleagueA); ok {
   
        m.colleagueB.receive()
    } else {
   
        m.colleagueA.receive()
    }
}func main() {
   
    mediator := &ConcreteMediator{
   }
    colleagueA := &ConcreteColleagueA{
   mediator}
    colleagueB := &ConcreteColleagueB{
   mediator}
    mediator.colleagueA = colleagueA
    mediator.colleagueB = colleagueB
    colleagueA.send()
    colleagueB.send()
}

八、中介者模式的优缺点

{B11F162F-8DA7-44D7-96AB-3DE981752885}.png

(一)优点

降低耦合度

对象之间不再直接交互,而是通过中介者进行通信,大大降低了对象之间的依赖关系,使得系统更加灵活,易于维护和扩展。

简化对象交互逻辑

将复杂的多对多对象交互逻辑集中到中介者对象中,使得交互逻辑更加清晰,便于理解和管理。

提高代码复用性

中介者对象可以被多个对象复用,提高了代码的复用性。

(二)缺点

中介者可能变得复杂

随着系统功能的增加,中介者对象可能会承担过多的交互逻辑,变得过于复杂,难以维护。

降低对象的自主性

对象的行为在一定程度上依赖于中介者,可能会降低对象自身的自主性和可复用性。
{445BADEE-F9DF-4F46-9982-CDA03A9014CA}.png

九、中介者模式的升级版

{661AC527-84D2-4B8B-9926-AEC98F029F1C}.png

分层中介者模式

在大型系统中,可以采用分层中介者模式。将中介者分为多个层次,每个层次的中介者负责处理特定范围内的对象交互。例如,在企业级应用中,可以有部门级中介者和公司级中介者。部门级中介者处理部门内部对象的交互,公司级中介者协调部门之间的交互。这种分层结构可以进一步降低耦合度,提高系统的可维护性和扩展性。

分布式中介者模式

在分布式系统中,可以采用分布式中介者模式。将中介者功能分布在多个节点上,通过网络通信来协调对象之间的交互。这种模式可以提高系统的容错性和性能,适用于大规模分布式应用场景。

目录
相关文章
|
13天前
|
设计模式 存储 Java
【再谈设计模式】备忘录模式~对象状态的守护者
备忘录模式属于行为型设计模式。它的主要目的是在不破坏对象封装性的前提下,捕获并外部化一个对象的内部状态,以便之后可以将该对象恢复到这个状态。原发器(Originator):创建一个备忘录,用于记录当前时刻它的内部状态。原发器还可以使用备忘录来恢复其内部状态。备忘录(Memento):存储原发器对象的内部状态。备忘录应该防止原发器以外的其他对象访问其内部状态。负责人(Caretaker):负责保存备忘录,但不能对备忘录的内容进行操作或检查。
181 82
|
1月前
|
设计模式 Java Go
【再谈设计模式】状态模式~对象行为的状态驱动者
状态模式属于行为型设计模式。它将对象的行为封装在不同的状态类中,使得对象在不同的状态下表现出不同的行为。上下文(Context):这是一个包含状态对象的类,它定义了客户感兴趣的接口,并维护一个具体状态对象的引用。上下文将操作委托给当前的状态对象来处理。抽象状态(State):这是一个抽象类或者接口,它定义了一个特定状态下的行为接口。所有具体的状态类都实现这个接口。具体状态(Concrete State):这些是实现抽象状态接口的类,每个具体状态类实现了与该状态相关的行为。
74 18
|
20天前
|
设计模式 算法 Java
【再谈设计模式】访问者模式~操作对象结构的新视角
  访问者模式是一种行为设计模式,旨在解决对象结构与操作逻辑的耦合问题。在软件系统开发中,当面临复杂的对象结构(如多种类型对象组成的树形或图形结构),且需要对这些对象执行不同操作时,传统方式将操作直接写在对象类中会导致类职责过多,不利于维护和扩展。而访问者模式通过将操作与对象结构分离,允许在不改变现有对象结构的情况下定义新操作,元素接受访问者访问,访问者定义对不同类型元素的操作逻辑,从而为应对这种复杂情况提供了有效的解决方案。
26 0
|
6月前
|
设计模式 Java
Java设计模式-中介者模式(20)
Java设计模式-中介者模式(20)
|
7月前
|
设计模式 前端开发 Java
【十三】设计模式~~~行为型模式~~~中介者模式(Java)
文章详细介绍了中介者模式(Mediator Pattern),这是一种对象行为型模式,用于封装一系列对象的交互,降低系统耦合度,并简化对象之间的交互关系。通过案例分析、结构图、时序图和代码示例,文章展示了中介者模式的组成部分、实现方式和应用场景,并讨论了其优点、缺点和适用情况。
【十三】设计模式~~~行为型模式~~~中介者模式(Java)
|
8月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
113 1
|
8月前
|
设计模式 JavaScript
js设计模式【详解】—— 中介者模式
js设计模式【详解】—— 中介者模式
101 5
|
7月前
|
设计模式 存储 安全
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
159 0
|
3月前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
177 11
|
10天前
|
设计模式 Java 关系型数据库
设计模式:工厂方法模式(Factory Method)
工厂方法模式是一种创建型设计模式,通过将对象的创建延迟到子类实现解耦。其核心是抽象工厂声明工厂方法返回抽象产品,具体工厂重写该方法返回具体产品实例。适用于动态扩展产品类型、复杂创建逻辑和框架设计等场景,如日志记录器、数据库连接池等。优点包括符合开闭原则、解耦客户端与具体产品;缺点是可能增加类数量和复杂度。典型应用如Java集合框架、Spring BeanFactory等。

热门文章

最新文章