TypeScript类似Java的Builder模式:父类链式调用赋值失败问题
解决TypeScript井字棋Builder模式父类属性不生效的问题
你遇到的问题核心是子类的Builder没有正确关联父类Player的symbol属性设置逻辑,导致调用setSymbol时没有把值真正赋给实例的父类属性。以下是几种不用把setter/getter移到子类的解决方法:
方法1:抽离通用PlayerBuilder基类复用逻辑
把父类属性的设置逻辑抽象到基类Builder中,子类Builder继承后只处理自身特有的属性,避免重复代码:
enum TicTacToeSymbol { X = 'X', O = 'O' } // 抽象父类Player abstract class Player { private _symbol: TicTacToeSymbol; get symbol(): TicTacToeSymbol { return this._symbol; } set symbol(value: TicTacToeSymbol) { this._symbol = value; } } // 人类玩家子类 class HumanPlayer extends Player { private _name: string; get name(): string { return this._name; } set name(value: string) { this._name = value; } static builder() { return new HumanPlayerBuilder(); } } // 通用父类Builder,处理symbol属性 abstract class PlayerBuilder<T extends Player> { protected player: T; constructor(player: T) { this.player = player; } setSymbol(symbol: TicTacToeSymbol): this { this.player.symbol = symbol; return this; } abstract build(): T; } // 人类玩家Builder,继承通用Builder并处理name属性 class HumanPlayerBuilder extends PlayerBuilder<HumanPlayer> { constructor() { super(new HumanPlayer()); } setName(name: string): this { this.player.name = name; return this; } build(): HumanPlayer { return this.player; } }
调用示例:
const human = HumanPlayer.builder().setName('XYZ').setSymbol(TicTacToeSymbol.X).build(); console.log(human.symbol); // 输出X,设置生效
方法2:直接在子类Builder中操作父类属性
如果不想额外定义基类Builder,可在子类的静态builder方法中直接处理父类属性:
enum TicTacToeSymbol { X = 'X', O = 'O' } abstract class Player { private _symbol: TicTacToeSymbol; get symbol(): TicTacToeSymbol { return this._symbol; } set symbol(value: TicTacToeSymbol) { this._symbol = value; } } class HumanPlayer extends Player { private _name: string; get name(): string { return this._name; } set name(value: string) { this._name = value; } static builder() { const player = new HumanPlayer(); return { setName(name: string) { player.name = name; return this; }, setSymbol(symbol: TicTacToeSymbol) { // 直接调用父类setter player.symbol = symbol; return this; }, build() { return player; } }; } }
这种方式无需额外创建Builder类,直接在静态方法中返回包含所有属性设置逻辑的对象,同样能确保symbol被正确赋值。
方法3:子类Builder直接访问父类属性
如果用独立的Builder类实现,只要在setSymbol方法中直接通过实例调用父类的setter即可:
class HumanPlayerBuilder { private player: HumanPlayer; constructor() { this.player = new HumanPlayer(); } setName(name: string): this { this.player.name = name; return this; } setSymbol(symbol: TicTacToeSymbol): this { this.player.symbol = symbol; return this; } build(): HumanPlayer { return this.player; } } // HumanPlayer类中返回Builder实例 class HumanPlayer extends Player { // ... 其他代码 static builder() { return new HumanPlayerBuilder(); } }
核心逻辑都是让Builder能够正确调用父类Player的symbol setter,既保留了父类的属性复用,又解决了属性不生效的问题。
内容的提问来源于stack exchange,提问作者ajayv
相关产品推荐
相关产品推荐

