【愚公系列】2023年10月 二十三种设计模式(十七)-中介者模式(Mediator Pattern)

举报
愚公搬代码 发表于 2021/12/04 19:39:09 2021/12/04
【摘要】 设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

毫无疑问,设计模式对个人、团队和整个系统都带来了显著的益处。它们将代码开发提升到工程化水平,为软件工程构建提供了坚实的基础,就如同大厦的一块块精巧的砖石一样。在项目中明智地应用设计模式可以完美地解决各种复杂问题。每种设计模式都有相应的原理和最佳实践,它们描述了我们日常开发中不断遇到的问题,以及这些问题的核心解决方法。正是因为这种实用性和通用性,设计模式才能在软件开发中广泛地得以应用。设计模式是构建稳健、可扩展和可维护软件的关键工具,为开发者们提供了解决问题的智慧和指导。

🚀一、中介者模式(Mediator Pattern)

中介者模式是一种行为型设计模式,它用于管理一组对象之间的相互作用,以实现对象之间的解耦。在这种模式下,多个对象不需要直接相互通信,而是通过一个中介者对象来协调它们之间的交互。

当一组对象需要进行复杂的相互协作时,中介者模式可以帮助降低系统的复杂性和耦合度。它的主要目标是确保对象之间的通信不会导致紧密耦合,从而使系统更加灵活、可维护和可扩展。

当某些对象之间的相互作用需要发生改变时,中介者模式可以轻松应对这种变化,而不需要修改每个对象的代码。这意味着中介者模式有助于保持系统的稳定性,并支持适应变化。

中介者模式是一种有助于管理对象之间复杂交互的设计模式,通过引入中介者对象,可以实现对象之间的松散耦合,提高系统的可维护性和可扩展性。这种模式在需要协调多个对象之间的场景下非常有用。

🚀二、使用步骤

🔎1.角色

🦋1.1 抽象中介者(Mediator)

解释器模式(Interpreter Pattern)和中介者模式(Mediator Pattern)是两种不同的设计模式,它们具有不同的概念和作用。让我们分别解释它们:

  1. 解释器模式 (Interpreter Pattern)

    • 解释器模式是一种行为型设计模式,它用于定义语言的文法规则,并且可以解释该语言中的表达式。这种模式的主要目的是创建一个解释器来解释和执行语言中的表达式,通常用于构建编程语言解释器、正则表达式引擎等。
    • 在解释器模式中,通常有两种重要的角色:
      • 终结符表达式(Terminal Expression):表示语言中的最小单元,可以是一个词法单元或一个操作符。
      • 非终结符表达式(Non-terminal Expression):表示由终结符表达式组成的复合表达式,通常表示语法规则中的语句或表达式。
    • 解释器模式的核心思想是将一个问题分解成一系列的表达式,并为每个表达式创建对应的解释器,然后通过组合这些解释器来解决问题。
  2. 中介者模式 (Mediator Pattern)

    • 中介者模式是一种行为型设计模式,它用于管理一组对象之间的相互作用,以实现对象之间的解耦。在这种模式下,多个对象不需要直接相互通信,而是通过一个中介者对象来协调它们之间的交互。
    • 中介者模式的主要目标是确保对象之间的通信不会导致紧密耦合,从而使系统更加灵活、可维护和可扩展。
    • 中介者模式通常包括以下角色:
      • 中介者(Mediator):负责协调对象之间的交互,包括接收和转发消息。
      • 同事对象(Colleague):彼此之间需要通信的对象,它们不直接相互通信,而是通过中介者来进行通信。
    • 中介者模式适用于需要多个对象协同工作的情况,以减少对象之间的直接依赖关系。

解释器模式主要用于解释语言表达式,将问题分解成表达式并解释执行;中介者模式用于管理对象之间的相互作用,协调对象之间的通信以减少耦合度。虽然它们都涉及对象之间的交互,但它们的核心概念和作用是不

🦋1.2 具体中介者(Concrete Mediator)

在解释器模式(Interpreter Pattern)中,并没有一个特定的"具体中介者(Concrete Mediator)"角色。中介者模式和解释器模式是两种不同的设计模式,它们解决的问题和角色有所不同。

中介者模式(Mediator Pattern)的核心概念是引入一个中介者对象,用于协调一组对象之间的相互作用,以降低这些对象之间的耦合度。中介者模式通常包括中介者角色(Mediator)和同事对象角色(Colleague)。

解释器模式(Interpreter Pattern)是一种行为型设计模式,用于定义语言的文法规则,并且可以解释该语言中的表达式。在解释器模式中,通常有终结符表达式(Terminal Expression)和非终结符表达式(Non-terminal Expression)等角色,用于表示语言中的表达式和规则。

这两种模式有不同的用途和关注点,因此没有一个称为"具体中介者(Concrete Mediator)"的角色出现在解释器模式中。如果你需要详细了解解释器模式或中介者模式的相关角色和用法,我可以为你提供更多信息。

🦋1.3 抽象同事类(Colleague)

在解释器模式(Interpreter Pattern)中,并没有抽象同事类(Abstract Colleague)的概念。中介者模式(Mediator Pattern)中有同事对象(Colleague)角色,但在解释器模式中并不涉及这个概念。

解释器模式主要包括以下关键角色:

  1. 抽象表达式(Abstract Expression):定义解释器的接口,包括一个interpret方法,用于解释表达式。

  2. 终结符表达式(Terminal Expression):实现抽象表达式接口,表示语言中的最小单元,可以是一个词法单元或一个操作符。

  3. 非终结符表达式(Non-terminal Expression):也实现抽象表达式接口,表示由终结符表达式组成的复合表达式,通常表示语法规则中的语句或表达式。

  4. 上下文(Context):包含解释器所需的信息和数据,通常用于存储和传递解释器需要的上下文信息。

解释器模式的核心思想是将一个问题分解成一系列的表达式,并为每个表达式创建对应的解释器,然后通过组合这些解释器来解决问题。它主要用于定义一种语言的语法规则,并解释和执行该语言中的表达式。

🦋1.4 具体同事类(Concrete Colleague)

解释器模式(Interpreter Pattern)通常不包括具体同事类(Concrete Colleague)的概念。具体同事类是中介者模式(Mediator Pattern)中的角色,而不是解释器模式中的角色。

在中介者模式中,具体同事类是系统中需要协作的多个对象,它们通过中介者对象来进行通信和协调。这些具体同事类通常实现一个共同的接口,并且持有一个对中介者对象的引用。中介者对象负责处理具体同事类之间的交互,以减少对象之间的直接依赖关系,从而提高系统的灵活性和可维护性。

在解释器模式中,主要包括以下角色:

  1. 抽象表达式(Abstract Expression):定义解释器的接口,包括一个interpret方法,用于解释表达式。

  2. 终结符表达式(Terminal Expression):实现抽象表达式接口,表示语言中的最小单元,可以是一个词法单元或一个操作符。

  3. 非终结符表达式(Non-terminal Expression):也实现抽象表达式接口,表示由终结符表达式组成的复合表达式,通常表示语法规则中的语句或表达式。

  4. 上下文(Context):包含解释器所需的信息和数据,通常用于存储和传递解释器需要的上下文信息。

解释器模式主要用于定义一种语言的语法规则,并解释和执行该语言中的表达式,不涉及具体同事类的概念。具体同事类是中介者模式中的概念,用于协作的多个对象之间的通信和协调。如果您需要了解更多关于中介者模式或其他设计模式的信息,请随时提问。

🔎2.示例

在这里插入图片描述

命名空间MediatorPattern中包含抽象用户类User充当同事基类,它有2个实现类,普通用户GeneralUser类和VIP用户VipUser类,聊天室ChatRoom类充当中介者基类,新浪聊天室SinaChat类为具体中介者。本案例尝试使用中介者模式实现应用最为广泛的网络聊天室。

public abstract class User {

    public string Name { get; private set; }

    protected User(string name) {
        Name = name;
    }

    public abstract void OnRecieve(User sender, string message, bool group = false);

}

抽象用户类User,内部仅维持一个姓名,OnRecieve方法定义在收到其他用户的信息时的回调。此处必须使用public公开OnRecieve方法,因为在聊天室中需要调用它。

public class GeneralUser : User {
 
    public GeneralUser(string name) : base(name) {
 
    }
 
    public override void OnRecieve(User sender, string message, bool group = false) {
        var groupFlag = group ? "group" : "private";
        Console.WriteLine(
            $"{this.IdentitySign()} recieved a {groupFlag} message from " +
            $"{sender.IdentitySign()},{Environment.NewLine}(s)he says:{message}");
    }
 
}

普通用户类GeneralUser,继承自User并实现OnRecieve方法。

public class VipUser : User {
 
    public VipUser(string name) : base(name) {
 
    }
 
    public override void OnRecieve(User sender, string message, bool group = false) {
        var groupFlag = group ? "group" : "private";
        Console.WriteLine(
            $"{this.IdentitySign()} recieved a {groupFlag} message from " +
            $"{sender.IdentitySign()},{Environment.NewLine}(s)he says:{message}");
    }
 
}

Vip用户类VipUser,继承自User并实现OnRecieve方法。实际开发过程中可不定义2个实现类,使用属性标识是否是Vip用户即可。

public abstract class ChatRoom {

    protected List<User> _users = null;

    protected const string SPLIT_BREAK =
        "------------------------------------------------------";

    protected ChatRoom() {
        _users = new List<User>();
    }

    public void Attach(User user) {
        if (user == null) throw new ArgumentNullException();
        _users.Add(user);
    }

    public bool Detach(User user) {
        if (user == null) throw new ArgumentNullException();
        return _users.Remove(user);
    }

    public abstract void Talk2All(User sender, string message);
    public abstract void Talk2User(User sender, User reciever, string message);

}

聊天室基类ChatRoom,需要维持对User列表的引用并包含添加和删除方法,包含2个主要方法,对所有人说话Talk2All和对某人说话Talk2User。

public class SinaChat : ChatRoom {

    public override void Talk2All(User sender, string message) {
        _users.Where(u => u.Name != sender.Name)
              .ToList()
              .ForEach((u) => u.OnRecieve(sender, message, true));
        Console.WriteLine(SPLIT_BREAK);
    }

    public override void Talk2User(User sender, User reciever, string message) {
        var user = _users.Where(u => u.Name == reciever.Name)
                         .FirstOrDefault();
        user.OnRecieve(sender, message);
        Console.WriteLine(SPLIT_BREAK);
    }

}

具体聊天室,实现对所有人说话Talk2All和对某人说话Talk2User方法。

public static class Extentions {
 
    public static string IdentitySign(this User user) {
        if (user is VipUser) {
            return $"{user.Name}[VIP]";
        }
        else if (user is GeneralUser) {
            return $"{user.Name}";
        }
        return string.Empty;
    }
 
}

定义了一个扩展以方便展示用户Vip标识。

public class Program {

    private static ChatRoom _chatRoom;

    public static void Main(string[] args) {
        _chatRoom = new SinaChat();

        var juice = new GeneralUser("Juice");
        var cola = new GeneralUser("Cola");
        var iori = new VipUser("Iori");
        var marin = new VipUser("Marin");

        _chatRoom.Attach(juice);
        _chatRoom.Attach(cola);
        _chatRoom.Attach(iori);
        _chatRoom.Attach(marin);

        _chatRoom.Talk2All(juice, "Hello Every one!");
        _chatRoom.Talk2User(cola, iori, "Hello Iori!");
        _chatRoom.Talk2User(iori, marin, "Hello Marin!");

        Console.ReadKey();
    }

}

以上是调用方的代码演示,以下是这个案例的输出结果:

Cola recieved a group message from Juice,
(s)he says:Hello Every one!
Iori[VIP] recieved a group message from Juice,
(s)he says:Hello Every one!
Marin[VIP] recieved a group message from Juice,
(s)he says:Hello Every one!
------------------------------------------------------
Iori[VIP] recieved a private message from Cola,
(s)he says:Hello Iori!
------------------------------------------------------
Marin[VIP] recieved a private message from Iori[VIP],
(s)he says:Hello Marin!
------------------------------------------------------

🚀总结

🔎1.优点

中介者模式(Mediator Pattern)有许多优点,它被用于协调多个对象之间的通信和交互,以减少对象之间的耦合度。以下是中介者模式的一些主要优点:

  1. 减少耦合度(Reduced Coupling):中介者模式将对象之间的直接通信替换为与中介者的间接通信,从而降低了对象之间的耦合度。这使得系统更容易维护和扩展,因为对象不再直接依赖于其他对象。

  2. 集中控制(Centralized Control):中介者充当了对象之间的中心控制器,可以更容易地管理和协调对象之间的交互。这有助于确保对象之间的通信不会导致混乱或不一致的状态。

  3. 简化对象(Simplified Objects):由于对象不再需要了解其他对象的详细信息,因此可以更简化对象的设计。对象只需要知道如何与中介者通信即可,不需要了解其他对象的内部实现。

  4. 可复用性(Reusability):中介者模式可以使中介者对象在不同的上下文中重复使用,从而提高了代码的可复用性。只需更改中介者对象的实现,而不需要修改与其交互的对象。

  5. 易于扩展(Ease of Extensibility):向系统中添加新的对象或更改现有对象的行为相对容易,因为这些更改通常只需要修改中介者对象而不是所有相关对象。

  6. 降低通信复杂性(Reduced Communication Complexity):中介者模式可以将复杂的通信逻辑集中在一个地方,使系统的通信更加简单和可管理。

  7. 支持松散耦合(Support for Loose Coupling):中介者模式促进了松散耦合的设计,使得对象可以独立开发和测试,然后在系统中通过中介者进行集成。

中介者模式有助于提高系统的可维护性、可扩展性和灵活性,特别适用于需要多个对象协同工作的复杂系统。它可以有效地管理对象之间的关系,减少了代码中的混乱和复杂性,使系统更加清晰和

🔎2.缺点

中介者模式(Mediator Pattern)虽然有许多优点,但也存在一些缺点和限制,需要在使用时考虑:

  1. 复杂性增加(Increased Complexity):引入中介者对象会增加系统的复杂性,特别是当系统中有大量的对象需要协调时。中介者模式可能会导致中介者对象变得复杂,难以维护和理解。

  2. 单点故障(Single Point of Failure):中介者对象成为系统中的单点故障。如果中介者对象发生故障或出现问题,整个系统的通信和协调可能会受到影响。

  3. 性能开销(Performance Overhead):由于所有通信都通过中介者对象进行,可能会引入一定的性能开销。在大规模系统中,这可能会导致性能问题。

  4. 限制对象直接通信(Restricts Direct Communication):中介者模式要求对象之间只能通过中介者进行通信,这可能限制了一些直接的对象之间的有效通信。有时候,直接通信可能更高效或更合适。

  5. 复杂的中介者对象(Complex Mediator):如果中介者对象的设计不合理,可能会变得非常复杂,难以维护和扩展。需要小心设计中介者以避免这种情况。

  6. 不适用于所有情况(Not Suitable for All Cases):中介者模式适用于需要对象之间松散耦合的情况,但并不适用于所有情况。在一些情况下,其他设计模式可能更合适。

  7. 增加代码复杂性(Increased Code Complexity):在一些情况下,引入中介者模式可能会增加代码的复杂性,而不是简化它。这取决于系统的结构和需求。

在使用中介者模式时,开发人员应仔细权衡其优点和缺点,确保它适合特定的系统和需求。中介者模式通常在需要对象之间的松散耦合和协调的情况下发挥最大的作用。

🔎3.使用场景

中介者模式(Mediator Pattern)适用于以下情况和场景:

  1. 多个对象之间的通信复杂:当系统中的多个对象之间需要频繁通信和协作,但直接的对象之间的耦合度较高,导致系统难以维护和扩展时,中介者模式可以帮助降低复杂性。

  2. 避免对象之间的直接依赖关系:中介者模式可以减少对象之间的直接依赖关系,使得各个对象可以独立开发、测试和维护,从而提高系统的灵活性。

  3. 一对多关系:当一个对象需要与多个其他对象进行通信和协作,而且这些对象之间的关系复杂时,中介者模式可以帮助简化对象之间的通信。

  4. 系统中对象交互频繁:如果系统中的对象之间需要频繁地进行通信和交互,但这种交互导致了复杂的依赖关系网,中介者模式可以帮助整理和管理这些交互。

  5. 分布式系统:在分布式系统中,中介者模式可以用于管理分布在不同节点上的对象之间的通信和协作,以确保分布式系统的一致性和可扩展性。

  6. 事件驱动系统:中介者模式在事件驱动系统中非常有用,其中多个对象可以发布和订阅事件,中介者可以负责协调事件的分发和处理。

  7. 图形用户界面(GUI)应用程序:在GUI应用程序中,用户界面元素(如按钮、文本框、复选框等)之间需要相互响应和协作。中介者模式可以用于管理用户界面元素之间的交互。

  8. 游戏开发:在游戏开发中,多个游戏对象之间需要协作和通信,例如角色之间的互动、敌人的行为控制等。中介者模式可以帮助管理这些游戏对象之间的关系。

中介者模式适用于需要降低对象之间耦合度、简化通信和协作、提高系统可维护性和灵活性的情况。在设计复杂的系统中,中介者模式可以帮助管理对象之间的关系,提高系统的可理解性和可扩展性。


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

在这里插入图片描述

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。