面向对象桌游核心逻辑应以player、turn、action三类高内聚划分,封装私有状态并提供语义化接口;用组合替代继承支持规则变体,不可变数据与显式上下文传递降低耦合。

用面向对象配合封装思想编写高内聚的桌游核心逻辑组件,关键在于:把游戏规则中稳定、独立的“概念实体”建模为类,隐藏内部状态变更细节,只暴露明确语义的操作接口,并让每个类职责单一、协作清晰。
以“玩家-回合-动作”为边界划分核心类
避免写一个大而全的 GameEngine 类。从桌游运行的本质节奏切入——玩家在回合中执行动作。由此自然拆出三个高内聚类:
-
Player:只管自身状态(手牌、资源、身份标记),不感知其他玩家或全局规则;提供
playCard(card)、gainResource(amount)等带业务语义的方法,而非开放resources += amount这类裸操作。 -
Turn:封装回合生命周期(开始→行动阶段→结束)、阶段切换逻辑和阶段合法性检查(如“仅限本阶段使用技能”);对外只暴露
nextPhase()、canAct()等控制流接口。 -
Action(抽象基类):定义
execute(context)和isValid(context)统一契约;具体动作(如AttackAction、DrawCardAction)只实现自身规则,不耦合玩家或回合状态。
用私有状态 + 受控变更保障封装性
所有影响游戏状态的字段必须设为私有(如 Python 的 _hand、TypeScript 的 private hand: Card[]),禁止直接读写。变更只能通过方法触发,且方法需做完整性校验:
- 在
Player.discard(card)中,先检查card是否真在手牌里,再移除并触发 “弃牌后摸一张” 效果(如果规则允许); - 在
Turn.start()中,自动重置行动点、清空本回合已用技能列表,并广播turnStarted事件——这些细节对调用方透明,但保证每次回合开始状态一致。
用组合代替继承表达规则变体
不同桌游规则差异大,硬套继承链易僵化。优先用组合注入行为:
- 把胜负判定逻辑抽成
WinCondition接口,实现类如FirstTo10PointsWin或ControlThreeZonesWin;Game类持有一个winCondition: WinCondition实例,运行时替换即可支持不同胜利方式; - 将卡牌效果建模为
Effect对象(如DamageEffect(target, 2)、DrawEffect(player, 1)),Card类只持有effects: Effect[],执行时遍历调用apply()——新增卡牌无需改Card类,只需定义新Effect子类。
用不可变数据 + 显式上下文传递减少隐式依赖
避免方法内部偷偷访问单例或全局状态。每个动作执行时,显式传入所需上下文(如 GameState 快照或只读视图):
-
action.execute({ player, opponents, board, rules })—— 所有依赖一目了然; -
GameState本身设计为不可变:gameState.withPlayerUpdated(newPlayer)返回新实例,旧状态保留,方便回滚、AI模拟或网络同步。
不复杂但容易忽略:高内聚不是堆砌类,而是让每个类回答清楚“我唯一负责什么”“谁该找我做事”“我绝不碰哪些东西”。封装不是加 private 就完事,是把变化关进方法里,让外部只和意图对话,不和实现纠缠。











