《设计模式与游戏完美开发》——第五周读书笔记

本文深入探讨中介者模式在游戏开发中的应用,通过实例讲解如何利用该模式降低子系统间的耦合度,实现功能模块间的高效协作。

在上一周的读书笔记中,我简单的介绍了单例模式,在本周的读书笔记中我将介绍中介者模式。
前言
我在之前已经提到过,一个完美的游戏应该是有许多的功能,并且由这些功能子系统组合而成一个完美的游戏。这些子系统有:游戏事件系统、角色系统、背包系统、成就系统、体力系统、战斗系统、游戏状态界面等等。而根据单一职责原则来讲,这些子系统的功能应该比较单一,那么要想实现比较多的功能,可能就需要很多的这些子系统类。在外观模式中,我们已经给出了如何让这些子系统面对客户端——封装一个高级界面,以此来降低客户端对游戏系统的接触和耦合,但是高级界面之下这些子系统之间,我们是如何采取沟通的呢?
一般方式
比如MMORPG的一个常见打副本的操作,当玩家点击了进入某一个副本的按钮后,组队系统首先工作来检测是否达到足够的人数,如果人数够了那么就会通知体力系统,如果体力系统够了那么就会进入副本系统,扣除体力,同时要启动战斗系统,其中某一条件不符合进入副本时候就会通知一些其他的提示系统,弹出ui进行提示。我们再具体一点,把系统看成一个个对象,所有系统的对象调用方法前都必须要实现其他的对象,或者在调用方法时传参数,但这些方式会增加系统之间的依赖程度,也与最少知识原则相抵触了。这就出现比较矛盾的问题了,一方面需要功能比较单一的子系统,一方面又不希望这些子系统产生过多的“瓜葛”。就会出现类似如下图的矛盾:
在这里插入图片描述
不管你们是怎么看的,我是一想起一个方法里面如果要有这么多对象的引用,可能十分钟我就头晕了。那么这个时候就请出来我们的正主——中介者模式
中介者模式的定义
在本书原话中的说明是:“定义一个接口用来封装一群对象的互动行为。中介者通过移除对象之间的引用,来减少它们之间的耦合度,并且能改变它们之间的互动独立性。”这句话比较抽象而本书中也举了一个比较有趣的例子,
“设置一个物品集货中心,让所有收货点的物品都必须先集中到集货中心后,再被分派出去,各个集货点之间并不需要知道其他集货点的位置。”这里的集货中心就是相当于接口封装了这些对象的互动行为,所有的货需要先发到集货中心再由集货中心统一分派,这样就移除了对象之间(各个集货点)之间的直接往来。
中介者模式的说明
在这里插入图片描述
我来介绍一下其中的参与者:
Colleague(同事接口):
拥有一个Mediator属性成员,可以通过它来调用中介者的功能。
ConcreteColleagueX(同事接口实现类):
实现Colleague界面的类。
Mediator(中介者接口)、ConcreteMediator(中介者接口实现类):
由mediator类定义让Colleague类操作的接口
Concretemediator实现类中保护所有concretecolleague的对象引用。
concretemediator类之间的互动会发生在concretemediator类之间。
中介者模式实现范例
模拟代码如下

using System;
//中介者模式
namespace 中介者模式
{
    public abstract class Colleague
    {
        protected Mediator m_Mediator = null;//通过Mediator对外沟通 指向中介者 在建造者中被指定 Concrete会继承这个抽象类并实现
        public Colleague(Mediator theMediator)
        {
            m_Mediator = theMediator;
        }
        //Mediator的通知请求
        public abstract void Requset(string Message);
    } 
    
    public class ConcreteColleague1: Colleague
    {
        //获得一个mediator属性成员
        public ConcreteColleague1(Mediator theMediator) : base(theMediator) { }
        //执行动作
        public void Action()
        {
            //执行这个类需要进行的操作
            //通知其他的Colleague

            m_Mediator.SendMessage(this, "Colleague1发出通知");

        }
        //mediator通知请求
        public override void Requset(string Message)
        {
            Console.WriteLine("ConcreteColleague1.Requset" + Message);
        }
    }
    public class ConcreteColleague2 : Colleague
    {
        //获得一个mediator属性成员
        public ConcreteColleague2(Mediator theMediator) : base(theMediator) { }
        //执行动作
        public void Action()
        {
            //执行这个类需要进行的操作
            //通知其他的Colleague

            m_Mediator.SendMessage(this, "Colleague2发出通知");

        }
        //mediator通知请求
        public override void Requset(string Message)
        {
            //这里只是模拟所以仅仅是使用了一个打印消息 实际上这里可能是如果传入是c1那么c2就调用这个然后传一些参数以此做到两个系统配合工作
            Console.WriteLine("ConcreteColleague2.Requset" + Message);
        }
    }
    //用来管理Colleague对象的接口
    public abstract class Mediator
    {
        public abstract void SendMessage(Colleague thecolleague, string Message);
    }
    public class ConcreteMediator : Mediator
    {
        //把那些子系统类对象引用 全部注册进来
        ConcreteColleague1 m_colleague1 = null;
        ConcreteColleague2 m_colleague2 = null;
        public void SetColleague1(ConcreteColleague1 thecolleague)
        {
            m_colleague1 = thecolleague;
        }
        public void SetColleague2(ConcreteColleague2 thecolleague)
        {
            m_colleague2 = thecolleague;
        }
        //收到来自Colleague的通知请求
        public override void SendMessage(Colleague thecolleague, string Message)
        {
            //以下代码因为只是模拟 而且只有2个子系统 C1和C2为了体现工作肯定只有通知另外一个 
            //而在项目里实际上这里的string message可能是一些很重要的参数因为这个工作中心注册了其他子系统的对象这里可能就是通过request传参数 
            //从而做到让其他的子系统和自己配合
            //收到C1的通知C2
            if (m_colleague1 == thecolleague)
            {
                m_colleague2.Requset(Message);
            }
            //收到C2的通知C1
            if (m_colleague2 == thecolleague)
            {
                m_colleague1.Requset(Message);
            }
        }
    }
    //进行测试
    class Program
    {
        static void Main(string[] args)
        {
            //产生中介者
            ConcreteMediator pMediator = new ConcreteMediator();
            //产生两个子系统类
            ConcreteColleague1 concreteColleague1 = new ConcreteColleague1(pMediator);
            ConcreteColleague2 concreteColleague2 = new ConcreteColleague2(pMediator);
            //将其设置给中介者
            pMediator.SetColleague1(concreteColleague1);
            pMediator.SetColleague2(concreteColleague2);

            //执行
            concreteColleague1.Action();
            concreteColleague2.Action();
            Console.ReadKey();
        }
    }
}

运行结果
在这里插入图片描述
从运行结果看,这两者确实完成了交互因为在主函数里面,我先执行C1类的功能方法,然后C2就立马配合响应,再执行C2类的功能方法,然后C1立马又配合响应。从效果看确实做到了子系统相互搭配,那么这个中介者模式的优点在哪儿呢?我们可以看到C1和C2类里面并没有注册其他子系统的引用,首先从代码量上就可以减少很多了(每一个子系统都要注册其他子系统的对象,这样一来无论是内存,还是对于程序员心情都很难受)。大概工作流程:就是一旦执行某一个子系统类的Action他会通过中介者的sendmessage发出消息(这个是每一个子系统都注册了一个中介者),然后在中介者中会通过一些逻辑判断,这些判断主要是判断这个子系统需要哪些功能响应,然后直接调用已经在中介者中注册的其他需要配合子系统的Requset接受这个sendmessage以此来实现各个子系统搭配。
至此,就是本周的读书笔记。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风萧水寒人往前

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值