ExpressJS中改造单例Player类以实现两个独立实例的技术问题
石头剪刀布游戏:玩家分数独立统计的修复方案
问题根源
你的Player类实现了单例模式,通过静态instance属性和getInstance()方法确保整个应用中只有一个Player实例。这导致initPlayers中间件里的player1和player2指向同一个对象,所以任意一方调用addPoint()时,两个"玩家"的分数都会同步增加。
修复步骤
1. 移除Player类的单例实现
单例模式是问题核心,我们需要让每次创建Player都生成独立实例,删掉所有单例相关的静态属性和方法:
export class Player { private _score: number; // 改为私有属性,通过getter访问 constructor() { this._score = 0; } addPoint() { this._score += 1; } // 添加score的getter,供外部读取分数 get score() { return this._score; } }
2. 修改initPlayers中间件,创建独立实例
不再使用getInstance(),直接通过new Player()生成两个独立的玩家对象:
export const initPlayers = (req: Request, _: Response, next: NextFunction) => { req.body = { ...req.body, player1: new Player(), player2: new Player(), }; next(); };
3. 修复Game类的ruleSet引用问题
原Game类构造函数未接收ruleSet参数,且方法内直接引用全局变量,修改为实例属性:
export class Game { ruleSet: IRuleSet[]; player1: Player; player2: Player; // 构造函数添加ruleSet参数 constructor(player1: Player, player2: Player, ruleSet: IRuleSet[]) { this.player1 = player1; this.player2 = player2; this.ruleSet = ruleSet; } whoWins(player1Choice: string, player2Choice: string): { message: string } { console.log(player1Choice, player2Choice); // 遍历实例的ruleSet属性,而非全局变量 for (const [_, rule] of this.ruleSet.entries()) { if (player1Choice === rule.choice) { if (rule.losesTo.includes(player2Choice)) { this.player2.addPoint(); return { message: `Player 2 Wins with ${player2Choice}`, }; } else if (rule.beats.includes(player2Choice)) { this.player1.addPoint(); return { message: `Player 1 Wins with ${player1Choice}`, }; } else { return { message: 'Draw', }; } } } return { message: 'Invalid Choice', }; } }
4. 修复Controller的Game实例初始化
创建Game时传入ruleSet参数,确保逻辑正常运行:
// 引入你定义好的ruleSet常量 import { ruleSet } from './path-to-your-ruleSet'; public play(req: Request, res: Response) { const { player1Move, player2Move, player1, player2 } = req.body; // 传入ruleSet参数 const game = new Game(player1, player2, ruleSet); const result = game.whoWins(player1Move, player2Move); console.log('SCORES', player1.score, player2.score); res.render('game', { data: req.body, player1Score: player1.score, player2Score: player2.score, }); }
验证效果
修改后,player1和player2将是完全独立的Player实例,调用addPoint()时只会修改对应玩家的分数,双方得分将被独立统计。
内容的提问来源于stack exchange,提问作者Exodus Reed
相关产品推荐
相关产品推荐

