• 基于Spring框架怎么构建游戏玩法服务


    说明:本篇阐述的问题,是基于前面的游戏服务器架构设计的。

    问题

    众所周知,Spring最擅长的领域是无状态服务的构建,而游戏(尤其是玩法部分)是有状态的。以棋牌游戏为例,玩法服务里面大概涉及以下两类对象:
    1、无状态的服务,比如数据读写、通信等;
    2、与游戏桌子绑定的有状态类,比如桌子本身,状态机,玩家的游戏状态等。
    后者肯定是要访问前者提供的方法的,那么后者怎么拿到前者的引用呢。

    我们一开始的做法是,无状态的服务做成Spring Bean,然后在启动的时候,把这些service的引用放到一个静态了类的字段里面,类似这样:

    public class ServiceContainer {
        public static ServiceBean1 bean1;
        public static ServiceBean2 bean2;
        ...
       
       public static init(ApplicationContext context)
        {
            bean1 = context.getBean(ServiceBean1.class);
            bean2 = context.getBean(ServiceBean2.class);
            ...
        }
    }
    

    然后有状态的对象就可以简单地通过ServiceContainer.bean1来访问无状态的服务了。
    不过代码多了以后,发现这种方式实在有点糟糕。 由于对ServiceContainer的访问实在太简单了,导致大家随意地在里面添加新的字段,最后对象之间的耦合依赖非常混乱,完全没有享受到使用Spring的好处。

    解决办法

    为了解决问题,首先确立一个原则,不允许通过静态方法、静态字段来暴露服务;单例模式当然也不允许(本质还是静态方法),既然用了Spring,就要按Spring的架构哲学来搞。
    第一个办法是这样的,在创建一个有状态的对象的时候,如果这个对象需要依赖某些Service,那么在初始化的过程中手动注入进去,以游戏桌table为例,代码类似这样:

    public class GameTable {
        public ServiceBean1 bean1;
        public ServiceBean2 bean2;
        ...
       
       public init(ApplicationContext context)
        {
            bean1 = context.getBean(ServiceBean1.class);
            bean2 = context.getBean(ServiceBean2.class);
            ...
        }
    }
    

    这个方法,虽然看起来和ServiceContainer半斤八两,但实际上要好很多,至少某个玩法的table依赖哪些服务一目了然。不过产品功能复杂性增加以后,table依赖的服务越来越多,还是会让人很不爽。

    继续优化方案

    table里面注入了太多的service,本质上说明游戏玩法逻辑的拆分不够细。
    在前边的文章里面,我们的核心玩法逻辑拆分成table(桌子),state(状态机),messageProcessor(消息处理器),现在重新捋一下这些角色的职责:

    1、table以及相关的类是游戏玩法的领域模型,专注于游戏的数据状态和基本规则算法;
    2、state状态机用来简化流程控制,专注于消息的过滤,和状态的切换;
    3、messageProcessor,专注于消息的处理,服务于玩法的所有桌子,也就是说它是无状态的;
    4、其他业务逻辑,比如数据的存取,游戏日志处理,外围功能(比如任务)。

    其中table和state都是内存对象,而messageProcessor和其他逻辑都是标准的Service Bean,state将消息过滤后,委托给messageProcessor来处理,依据处理结果来迁移状态。
    一个典型的messageProcessor接口可能类似这样的:

    public boolean processPlayerJoin(Table table, Player player, Message message)
    {
        if (玩家是否满足入桌条件)
        {
             table.addPlayer(player);
             return true;
        }
        return false
    }
    
  • 相关阅读:
    如何让我domain里的机器都跟domain controller的时间保持一致?
    [PowerShell Utils] Create a list of virtual machines based on configuration read from a CSV file in Hyper-V
    Reboot server stuck at “Press ESC in 1 seconds to skip startup.nsh”
    [PowerShell Utils] Remotely install Hyper-V and Failover Cluster feature on a list of windows 2012 servers
    [PowerShell Utils] Automatically Change DNS and then Join Domain
    SharePoint 2016 IT Preview的新feature列表
    LeetCode Permutations问题详解
    Rotate Image 旋转图像
    单链表的快速排序(转)
    anagrams 查找序列里具有相同字符但顺序不同的单词
  • 原文地址:https://www.cnblogs.com/longhuihu/p/10820866.html
Copyright © 2020-2023  润新知