JavaScript:如何通过名称创建继承类实例并避免逻辑重复?
替代switch的棋子实例创建方案
你可以用类注册表映射的方式彻底消除重复的name逻辑,同时让代码更符合开闭原则(新增子类不用修改创建逻辑),下面是两种实用的实现方式:
方案一:静态注册表 + 子类自动注册
这种方式让每个子类在定义时主动注册到父类的静态映射表中,name字符串只需要在子类的构造函数和注册时各写一次(也可以通过提取常量进一步减少重复),完全避免switch里的冗余逻辑:
class Piece { // 静态映射表:存储棋子名称到类的对应关系 static pieceClasses = new Map(); constructor(name) { this.name = name; } // 注册方法:供子类调用 static registerPieceClass(name, cls) { this.pieceClasses.set(name, cls); } // 统一的实例创建方法 static createPiece(name) { const PieceClass = this.pieceClasses.get(name); if (!PieceClass) { throw new Error(`Unknown piece type: ${name}`); } return new PieceClass(); } } // 定义Rook子类并注册 class Rook extends Piece { constructor() { super('rook'); } } Piece.registerPieceClass('rook', Rook); // 定义Bishop子类并注册 class Bishop extends Piece { constructor() { super('bishop'); } } Piece.registerPieceClass('bishop', Bishop); // 使用示例 const myRook = Piece.createPiece('rook'); console.log(myRook instanceof Rook); // true console.log(myRook.name); // 'rook'
优势:
- 新增棋子子类时,只需要添加子类定义和一行注册代码,无需修改
createPiece方法 - name字符串的关联逻辑集中在子类自身,不会出现switch中与子类name不一致的问题
- 映射表的查询效率比switch更高(尤其是子类数量多的时候)
方案二:直接使用对象映射表
如果你的子类数量不多且不需要动态注册,也可以直接创建一个纯对象来存储名称与类的对应关系,写法更简洁:
class Piece { constructor(name) { this.name = name; } } class Rook extends Piece { constructor() { super('rook'); } } class Bishop extends Piece { constructor() { super('bishop'); } } // 定义名称到类的映射 const pieceTypeMap = { rook: Rook, bishop: Bishop }; // 创建实例的函数 function createPiece(name) { const PieceClass = pieceTypeMap[name]; if (!PieceClass) { throw new Error(`Unknown piece type: ${name}`); } return new PieceClass(); } // 使用示例 const myBishop = createPiece('bishop');
优势:
- 代码量更少,适合简单场景
- 映射关系一目了然,比switch可读性更强
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

