10.中介者模式

10.行为型模式-中介者模式


10.1 基础知识

学习难度:3

使用频率:2

总分:5

定义

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

说人话

中介者就像是一个群聊,让各个同事作为用户进行聊天。

结构图

实现步骤

  • 中介者接口:定义中介者的通用方法,通常包括发送信息给所有同事的方法。
  • 具体中介者类:实现中介者接口,通常会维护一个同事列表进行维护并提供注册同时方法。发送信息给所有同事的方法时遍历同事列表让非自身的同事接收信息。
  • 抽象同事类:定义中介者对象并在构造函数初始化赋值,定义发送信息和接收信息的抽象方法。
  • 具体同事类:继承抽象同事类,发送消息时通过中介者的发送消息方法传输信息。
  • 客户端:实例化具体中介者类,然后实例化多个具体同事类,并将它们注册到中介者中,让具体同事发送消息。

说明

中介者模式适用于需要解耦多个对象之间的复杂交互情况。通过引入中介者对象,可以有效降低对象之间的直接依赖关系,提高代码的灵活性和可维护性。


10.2 模版代码

中介者接口和具体中介者

// 中介者接口
public interface IMediator
{
    void SendMessage(string message, AbstractColleague colleague);
}

// 具体中介者
public class ConcreteMediator : IMediator
{
    private List<AbstractColleague> colleagues = new List<AbstractColleague>();

    // 注册同事对象,使中介者知道所有的同事对象
    public void Register(AbstractColleague colleague)
    {
        colleagues.Add(colleague);
    }

    // 发送消息给所有同事
    public void SendMessage(string message, AbstractColleague sender)
    {
        foreach (AbstractColleague colleague in colleagues)
        {
            // 排除消息发送者自己
            if (colleague != sender)
            {
                colleague.ReceiveMessage(message);
            }
        }
    }
}

抽象同事类和具体同事类

// 抽象同事类
public abstract class AbstractColleague
{
    protected IMediator mediator;

    public AbstractColleague(IMediator mediator)
    {
        this.mediator = mediator;
    }

    // 发送消息给中介者
    public abstract void Send(string message);

    // 接收消息
    public abstract void ReceiveMessage(string message);
}

// 具体同事类A
public class ConcreteAbstractColleagueA : AbstractColleague
{
    public ConcreteAbstractColleagueA(IMediator mediator) : base(mediator) { }

    public override void Send(string message)
    {
        Console.WriteLine("同事A发送消息:" + message);
        mediator.SendMessage(message, this);
    }

    public override void ReceiveMessage(string message)
    {
        Console.WriteLine("同事A接收消息:" + message);
    }
}

// 具体同事类B
public class ConcreteAbstractColleagueB : AbstractColleague
{
    public ConcreteAbstractColleagueB(IMediator mediator) : base(mediator) { }

    public override void Send(string message)
    {
        Console.WriteLine("同事B发送消息:" + message);
        mediator.SendMessage(message, this);
    }

    public override void ReceiveMessage(string message)
    {
        Console.WriteLine("同事B接收消息:" + message);
    }
}

客户端

class Program
{
    static void Main(string[] args)
    {
        // 创建具体中介者对象
        ConcreteMediator mediator = new ConcreteMediator();

        // 创建具体同事对象
        AbstractColleague abstractColleagueA = new ConcreteAbstractColleagueA(mediator);
        AbstractColleague abstractColleagueB = new ConcreteAbstractColleagueB(mediator);

        // 注册同事对象到中介者
        mediator.Register(abstractColleagueA);
        mediator.Register(abstractColleagueB);

        // 同事A发送消息给同事B
        abstractColleagueA.Send("你好,同事B!");
        
        // 同事B发送消息给同事A
        abstractColleagueB.Send("嗨,同事A!");

        /*
        同事A发送消息:你好,同事B!
        同事B接收消息:你好,同事B!
        同事B发送消息:嗨,同事A!
        同事A接收消息:嗨,同事A!
        */
    }
}

10.3 CSharp实践

实践需求

使用中介者模式,模拟中美两国在联合国发言。

联合国接口和具体联合国类

// 中介者接口
public interface IUnitedNations
{
    void RegisterCountry(Country country);
    void Declare(string message, Country country);
}

// 具体中介者 - 联合国
public class UnitedNations : IUnitedNations
{
    private List<Country> countries = new List<Country>();

    public void RegisterCountry(Country country)
    {
        countries.Add(country);
    }

    public void Declare(string message, Country country)
    {
        Console.WriteLine($"联合国发布声明:{country.Name} 发表了 \"{message}\"");
    }
}

抽象国家类和具体国家类

// 抽象国家类 - 国家
public abstract class Country
{
    protected IUnitedNations unitedNations;

    public string Name { get; }

    public Country(string name, IUnitedNations unitedNations)
    {
        this.Name = name;
        this.unitedNations = unitedNations;
        unitedNations.RegisterCountry(this); // 将国家注册到联合国
    }

    public abstract void Declare(string message);
}

// 具体国家类 - 中国
public class China : Country
{
    public China(IUnitedNations unitedNations) : base("中国", unitedNations) { }

    public override void Declare(string message)
    {
        unitedNations.Declare(message, this);
    }
}

// 具体国家类 - 美国
public class USA : Country
{
    public USA(IUnitedNations unitedNations) : base("美国", unitedNations) { }

    public override void Declare(string message)
    {
        unitedNations.Declare(message, this);
    }
}

客户端

class Program
{
    static void Main(string[] args)
    {
        IUnitedNations unitedNations = new UnitedNations();
        Country china = new China(unitedNations);
        Country usa = new USA(unitedNations);

        china.Declare("中国强烈抗议某事件!");
        usa.Declare("美国支持某事件的决定!");

        /*
        联合国发布声明:中国 发表了 "中国强烈抗议某事件!"
        联合国发布声明:美国 发表了 "美国支持某事件的决定!"
        */
    }
}

10.4 Unity实践

实践需求

使用中介者模式,按下特定按键时,模拟剑圣和薇恩通过武魂融合技中介者发送武魂融合技请求,进行武魂融合技时的英雄都要释放技能。

抽象英雄伙伴类和具体英雄伙伴类

// 抽象英雄伙伴基类
public abstract class AbstractHeroColleague : MonoBehaviour
{
    protected IMartialSoulFusionTechniqueMediator mediator; // 中介者接口
    protected Animator animator; // 动画控制器

    private void Awake()
    {
        animator = GetComponent<Animator>(); // 获取Animator组件
    }

    // 设置中介者
    public void SetMediator(IMartialSoulFusionTechniqueMediator mediator)
    {
        this.mediator = mediator;
    }

    // 发送武魂融合技术请求的抽象方法
    public abstract void SendMartialSoulFusionTechniqueRequest(Type heroReceiverType);

    // 接收武魂融合技术请求的抽象方法
    public abstract void ReceiveMartialSoulFusionTechniqueRequest(AbstractHeroColleague heroSender);
}

// 薇恩伙伴类
public class VayneHeroColleague : AbstractHeroColleague
{
    // 发送武魂融合技术请求
    public override void SendMartialSoulFusionTechniqueRequest(Type heroReceiverType)
    {
        animator.SetTrigger("isSkill"); // 播放技能动画
        Debug.Log("薇恩使用了闪避突袭," + heroReceiverType + "快来和我一起进行武魂融合技"); // 打印技能使用信息
        mediator.SendMartialSoulFusionTechniqueRequest(this, heroReceiverType); // 通过中介者发送武魂融合技术请求
    }

    // 接收武魂融合技术请求
    public override void ReceiveMartialSoulFusionTechniqueRequest(AbstractHeroColleague heroSender)
    {
        animator.SetTrigger("isSkill"); // 播放技能动画
        Debug.Log("薇恩接收到" + heroSender + "发起的武魂融合技的邀请,薇恩使用了闪避突袭!"); // 打印接收到的请求信息
    }
}

// 剑圣伙伴类
public class YiHeroColleague : AbstractHeroColleague
{
    // 发送武魂融合技术请求
    public override void SendMartialSoulFusionTechniqueRequest(Type heroReceiverType)
    {
        animator.SetTrigger("isSkill"); // 播放技能动画
        Debug.Log("剑圣使用了阿尔法突袭," + heroReceiverType + "快来和我一起进行武魂融合技"); // 打印技能使用信息
        mediator.SendMartialSoulFusionTechniqueRequest(this, heroReceiverType); // 通过中介者发送武魂融合技术请求
    }

    // 接收武魂融合技术请求
    public override void ReceiveMartialSoulFusionTechniqueRequest(AbstractHeroColleague heroSender)
    {
        animator.SetTrigger("isSkill"); // 播放技能动画
        Debug.Log("剑圣接收到" + heroSender + "发起的武魂融合技的邀请,剑圣使用了阿尔法突袭!"); // 打印接收到的请求信息
    }
}

武魂融合技中介者接口和武魂融合技中介者

//武魂融合技中介者接口
public interface IMartialSoulFusionTechniqueMediator
{
    //注册武魂融合技英雄
    void RegisterHeroColleague(AbstractHeroColleague hero);
    void SendMartialSoulFusionTechniqueRequest(AbstractHeroColleague heroSender,Type heroReceiverType);
}

// 武魂融合技中介者类
public class MartialSoulFusionTechniqueMediator : IMartialSoulFusionTechniqueMediator
{
    // 用于存储不同类型英雄伙伴的字典
    private Dictionary<string, AbstractHeroColleague> heroColleaguesDictionary = new Dictionary<string, AbstractHeroColleague>();

    // 注册英雄伙伴
    public void RegisterHeroColleague(AbstractHeroColleague hero)
    {
        if (!heroColleaguesDictionary.ContainsKey(hero.GetType().ToString()))
        {
            heroColleaguesDictionary.Add(hero.GetType().ToString(), hero);
            hero.SetMediator(this);
        }
        else
        {
            Debug.Log("已经存在该英雄");
        }
    }

    // 发送武魂融合技术请求
    public void SendMartialSoulFusionTechniqueRequest(AbstractHeroColleague heroSender, Type heroReceiverType)
    {
        if (heroColleaguesDictionary.ContainsKey(heroReceiverType.ToString()))
        {
            heroColleaguesDictionary[heroReceiverType.ToString()].ReceiveMartialSoulFusionTechniqueRequest(heroSender);
        }
    }
}

客户端

public class TestMediatorPattern : MonoBehaviour
{
    private VayneHeroColleague vayneHeroColleague; // 薇恩英雄伙伴
    private YiHeroColleague yiHeroColleague; // 剑圣英雄伙伴

    private void Start()
    {
        // 创建武魂融合技术中介者对象
        MartialSoulFusionTechniqueMediator martialSoulFusionTechniqueMediator =
            new MartialSoulFusionTechniqueMediator();

        // 通过资源加载创建薇恩和剑圣的游戏对象
        GameObject vayne = Instantiate(Resources.Load<GameObject>("Lesson28_行为型模式_中介者模式/Vayne"));
        GameObject yi = Instantiate(Resources.Load<GameObject>("Lesson28_行为型模式_中介者模式/Yi"));

        // 从游戏对象获取对应的伙伴脚本组件
        vayneHeroColleague = vayne.GetComponent<VayneHeroColleague>();
        yiHeroColleague = yi.GetComponent<YiHeroColleague>();

        // 注册薇恩和剑圣伙伴到中介者
        martialSoulFusionTechniqueMediator.RegisterHeroColleague(vayneHeroColleague);
        martialSoulFusionTechniqueMediator.RegisterHeroColleague(yiHeroColleague);
    }

    private void Update()
    {
        // 检测按键输入,如果按下Q键,薇恩发起武魂融合技术请求给剑圣
        if (Input.GetKeyDown(KeyCode.Q))
        {
            vayneHeroColleague.SendMartialSoulFusionTechniqueRequest(typeof(YiHeroColleague));
        }

        // 检测按键输入,如果按下W键,剑圣发起武魂融合技术请求给薇恩
        if (Input.GetKeyDown(KeyCode.W))
        {
            yiHeroColleague.SendMartialSoulFusionTechniqueRequest(typeof(VayneHeroColleague));
        }
    }
}

运行结果



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏