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

发布于:2025-02-11 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、引言

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

二、定义与描述

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

三、抽象背景

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

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

(一)适用场景

GUI组件交互

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

游戏开发中的角色交互

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

分布式系统中的节点通信

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

(二)现实问题解决

降低耦合度

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

 

简化复杂交互逻辑

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

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

机场塔台

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

 

房屋中介

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

六、初衷与问题解决

初衷

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

问题解决

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

七、代码示例

类图:

(一)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();
}

// 具体同事类A
class 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);
    }
}

// 具体同事类B
class 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();
    }
}

流程图:

时序图:

(二)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;
};

// 具体同事类A
class 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);
    }
};

// 具体同事类B
class 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


# 具体同事类A
class ConcreteColleagueA(Colleague):
    def receive(self):
        print("ConcreteColleagueA received a message")

    def send(self):
        print("ConcreteColleagueA sends a message")
        self.mediator.notify(self)


# 具体同事类B
class 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 main

import (
    "fmt"
)

// 中介者接口
type Mediator interface {
    notify(colleague Colleague)
}

// 同事类接口
type Colleague interface {
    receive()
    send()
}

// 具体同事类A
type 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)
}

// 具体同事类B
type 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()
}

八、中介者模式的优缺点

(一)优点

降低耦合度

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

简化对象交互逻辑

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

提高代码复用性

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

 

(二)缺点

中介者可能变得复杂

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

降低对象的自主性

        对象的行为在一定程度上依赖于中介者,可能会降低对象自身的自主性和可复用性。

分类 描述
(一)优点
降低耦合度 对象之间通过中介者通信,降低对象间依赖关系,系统更灵活、易维护和扩展。
简化对象交互逻辑 复杂多对多交互逻辑集中到中介者,使交互逻辑更清晰、便于理解管理。
提高代码复用性 中介者可被多个对象复用。
(二)缺点
中介者可能变得复杂 系统功能增加时,中介者可能承担过多逻辑,难以维护。
降低对象的自主性 对象行为依赖中介者,可能降低自身自主性和复用性。

九、中介者模式的升级版

分层中介者模式

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

分布式中介者模式

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

模式 优势(Strengths) 劣势(Weaknesses) 机会(Opportunities) 威胁(Threats)
分层中介者模式 - 降低大型系统耦合度,提高可维护性和扩展性
- 明确不同层次中介者的职责范围,便于管理
- 增加系统复杂性,多层中介者间协调可能存在问题
- 层次划分不当可能导致职责混乱
- 适应企业级架构演进需求
- 可与其他企业级模式整合
- 企业架构变革可能使分层结构失效
- 竞争模式可能更具优势
分布式中介者模式 - 提高分布式系统的容错性
- 提升大规模分布式应用场景下的性能
- 网络通信可能带来延迟和可靠性问题
- 分布式协调增加了复杂度
- 适用于新兴的分布式计算趋势
- 可利用云计算资源提升性能
- 网络攻击可能破坏分布式协调
- 新技术可能替代该模式