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

问题

众所周知,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
}

基于Spring框架怎么构建游戏玩法服务的更多相关文章

  1. 基于Spring框架应用的权限控制系统的研究和实现

    摘 要: Spring框架是一个优秀的多层J2EE系统框架,Spring本身没有提供对系统的安全性支持.Acegi是基于Spring IOC 和 AOP机制实现的一个安全框架.本文探讨了Acegi安全 ...

  2. 简单Elixir游戏服设计- 游戏玩法介绍

    抄以前的,做了点修改. 到目前为止,我们完成了玩家的数据和进程建模,现在介绍游戏玩法. 为什么我们还不做客户端接入.协议指定呢?为什么还没有网关和数据存储呢.在我接手的游戏, 这些通常已经定下来了,我 ...

  3. 基于Spring框架的简单多数据源切换解决办法

    基于Spring框架的简单多数据源切换解决办法 Spring框架JDBC包提供了一个抽象类AbstractRoutingDataSource提供了动态切换数据库的基础方法.我们仅仅需要实现一个简单的数 ...

  4. 第一次玩博客,今天被安利了一个很方便JDBC的基于Spring框架的一个叫SimpleInsert的类,现在就来简单介绍一下

    首先先对这段代码的简单介绍,我之前在需要操作JDBC的时候总是会因为经常要重新写SQL语句感到很麻烦.所以就能拿则拿不能拿的就简单地封装了一下. 首先是Insert.Spring框架的JDBC包里面的 ...

  5. 基于Spring Boot+Cloud构建微云架构

    前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而来,很多描述的重点也都偏向于作者自身碰到的问题,这样就很容易让你理解和操作出现偏差 ...

  6. 轻量级高性能ORM框架:Dapper高级玩法

    Dapper高级玩法1: 数据库中带下划线的表字段自动匹配无下划线的Model字段. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 备 ...

  7. 使用 Spring Cloud Stream 构建消息驱动微服务

    相关源码: spring cloud demo 微服务的目的: 松耦合 事件驱动的优势:高度解耦 Spring Cloud Stream 的几个概念 Spring Cloud Stream is a ...

  8. 基于spring框架的apache shiro简单集成

    关于项目的安全保护,我一直想找一个简单配置就能达到目的的方法,自从接触了shiro,这个目标总算达成了,以下结合我使用shiro的经验,谈谈比较轻便地集成该功能. 首先我们先了解一下shiro是什么. ...

  9. 使用NetBeans搭建基于Spring框架的Web应用

    NetBeans下载链接:https://netbeans.org/. 第一步:选择“文件”菜单下的“新建项目”: 第二步:类别选择“Java Web”,项目选择“Web应用程序”,单击“下一步”: ...

随机推荐

  1. SVN限制IP访问

    转自:https://www.cnblogs.com/wjlkingwjl/p/4630764.html 需求 SVN是放在公网的,需要特别指定公司的IP才能获取操作. 操作 在安装完Visual S ...

  2. IDEA配置maven报错解决方案

    主要是得分清楚你的本地maven库,以及maven安装根目录 ,一般你自己安装maven成功后,电脑默认读取的库位置在C盘下面. 只要把路径指向搞对了,就没什么问题了 .

  3. Linux 磁盘、分区、文件系统、挂载

    磁盘 Linux所有设备都被抽象成为一个文件,保存在/dev目录下. 设备名称一般为hd[a-z]或sd[a-z].如果电脑中有多硬盘,则设备名依次为sda.adb.sdc...以此类推 IDE设备的 ...

  4. android开机启动流程说明

    android开机启动流程说明 第一步:启动linux 1.Bootloader 2.Kernel 第二步android系统启动:入口为init.rc(system\core\rootdir) 1./ ...

  5. Linux误删python导致yum不可用,删除重装方法。

    Linux 系统为 CentOS Linux release 7.4.1708 手贱.手贱.手贱 删了python 导致yum不可用.百度一大圈,重装yum和python后,老是报各种各样的错.历经磨 ...

  6. C++——Inheritence

    一种错误的观念: 子类继承父类,只把父类的公有成员继承下来,私有的不会继承. 事实上无论是如何继承,都会把父类的所有成员继承下来. #include<iostream> using nam ...

  7. 为0LTP选择RDMBS时,你都需要考虑哪些?

    我们经常需要为自己的OLTP(事务/运营)数据库选择适合的RDBMS(关系型数据库管理系统).虽然通过编写可移植的SQL可以暂时避免进行这样的选择,但迟早要做出这样的选择,至少需要进行这样的尝试(比如 ...

  8. SpringBoot下,@WebFilter配置获取日志

    CREATE TABLE [dbo].[SWEBSERVICELOG]( [WLG_ID] [varchar](100) NOT NULL, [WLG_SESSIONID] [varchar](100 ...

  9. frp服务搭建

    安装命令 C wget --no-check-certificate https://raw.githubusercontent.com/clangcn/onekey-install-shell/ma ...

  10. idea中tomcat的On Upate Action 与 On Frame Deactivation配置

    On Upate Action 与 On Frame Deactivation  这两个选项的设置,依赖于项目的部署方式 是war包 还是 exploded , 只讲exploded模式下的设置,因为 ...