高内聚桌游核心逻辑的关键是:用不可变值对象建模实体,以聚合根统一管理状态变更,通过策略+状态模式解耦规则分支,并用领域事件驱动松耦合协作。

用数据结构配合封装思想编写高内聚的桌游核心逻辑,关键在于:把游戏状态建模为不可变或受控可变的数据结构,把行为逻辑封装进职责单一、边界清晰的类中,让每个模块只关心“自己负责的那一部分规则”。不是堆砌设计模式,而是让数据和操作天然绑定,状态变更有迹可循,规则修改不牵一发而动全身。
用值对象建模不可变的游戏实体
玩家、卡牌、资源点这类有明确身份和属性的元素,应定义为不可变的值对象(Value Object)。比如一张卡牌,它的 ID、类型、效果描述、消耗成本在创建后就不该被外部修改。
- 用结构体(如 C++ 的 struct、Rust 的 struct、Java 的 record)或带私有字段+只读 getter 的类来实现
- 所有修改都通过返回新实例完成,例如
card.withCost(5)返回新卡牌,原卡不变 - 避免用 Map
或 JSON 对象承载核心实体——它们绕过了类型约束,也掩盖了业务语义
用聚合根统一管理有生命周期的领域模型
一局游戏本身、一个玩家的手牌区、一个战场区域,这些是存在内部一致性约束的聚合(Aggregate)。应选一个聚合根(如 GameSession)作为唯一入口,对外暴露有限且语义明确的操作接口。
一款AI工具,主要用于在主代理响应前,并行运行Kimi K2.5和GPT 5.3 Codex,注入双方观点以增强认知多样性,适合需要提升相关任务效率的用户。
-
GameSession持有Player列表、BoardState、TurnPhase等,但不暴露其内部集合的直接引用 - 所有变更必须走聚合根方法,如
session.playCard(playerId, cardId),由它校验是否轮到该玩家、手牌是否存在、费用是否足够 - 内部状态变更通过事件(如
CardPlayedEvent)通知监听者,而非让外部直接调用player.hand.remove(card)
用策略+状态模式解耦规则分支
桌游中大量逻辑依赖当前阶段(准备/行动/结算)、角色身份(攻击方/防御方)、卡牌类型(法术/随从/装备)。硬编码 if-else 易错且难维护。应把规则判断和执行提取为独立策略类。
- 定义
EffectExecutor接口,不同卡牌效果实现不同子类(DrawCardExecutor、DealDamageExecutor) - 用状态模式管理回合流程:
TurnState抽象类下分WaitingForActionState、ResolvingEffectState,状态切换时自动禁用非法操作 - 策略与状态的组合,让“打出一张抽牌卡”这件事,在不同阶段自动触发不同响应(比如结算阶段禁止出牌,直接抛异常)
用领域事件驱动松耦合协作
当一个动作引发多个下游反应(如“随从死亡” → “触发亡语” → “检查胜利条件” → “播放音效”),不要在主逻辑里写死调用链。改为发布领域事件,由各自订阅者响应。
- 定义
MinionDiedEvent(minionId, killerId, context),携带必要上下文,不含业务逻辑 -
DeathrattleHandler、VictoryChecker、AudioService各自监听并处理,互不影响 - 事件总线可用简单列表注册 + 同步分发,无需引入复杂框架;关键是要让“谁响应什么”显式可查,而非隐式散落在各处
不复杂但容易忽略:高内聚不是靠加 private 关键字实现的,而是靠让数据和它真正属于的操作待在一起——卡牌知道怎么计算自己的费用,回合知道怎么推进自己,玩家知道怎么验证自己能否行动。封装不是藏起来,而是说清楚“谁该对什么负责”。










