代码之家  ›  专栏  ›  技术社区  ›  Kirzilla

根据使用某个映射的输入对象创建新的对象实例

  •  0
  • Kirzilla  · 技术社区  · 5 年前

    假设我们有命令和命令处理程序。每个命令一个CommandHandler。

    解决方案应该在代码缩小后工作,并且应该是对重构友好的。

    目前我有这种解决方案,我个人不喜欢。

    interface Command {}
    class ConcreteCommand implements Command {}
    class ConcreteCommand2 implements Command {}
    
    interface CommandHandler {}
    class ConcreteCommandHandler implements CommandHandler {}
    class ConcreteCommand2Handler implements CommandHandler {}
    
    const map = [ //I don't like this kind of map, any other ways?
        [ConcreteCommand, ConcreteCommandHandler],
        [ConcreteCommand2, ConcreteCommand2Handler]
    ];
    
    function getCommandHandler(command: Command): CommandHandler {
        for(let pair of map) {
            if (command instanceof pair[0]) {
                return new pair[1];
            }
        }
        throw new Error('Unable to find CommandHandler.');
    }
    
    console.log( getCommandHandler(new ConcreteCommand()) ); //ConcreteCommandHandler
    

    This code at TypeScript Playground.

    0 回复  |  直到 5 年前
        1
  •  0
  •   Robbie Milejczak Diego Felipe    5 年前

    JavaScript有一个名为Map的数据类型。从 MDN :

    使用一个:

    const map = new Map()
    
    map.set(ConcreteCommand, ConcreteCommandHandler)
    
    const handler = new (map.get(ConcreteCommand))()
    

    需要注意的是,您的代码无法处理此问题,因为:

    getCommandHandler(new ConcreteCommand())
    

    每个实例都将被视为唯一的密钥。您可以使用函数本身,但是: map.set(ConcreteCommand)

        2
  •  0
  •   brunnerh    5 年前

    Maps 非常适合:

    const map = new Map<Command, CommandHandler>([
        [ConcreteCommand, ConcreteCommandHandler],
        [ConcreteCommand2, ConcreteCommand2Handler]
    ])
    
    function getCommandHandler(command: Command): CommandHandler
    {
        if (map.has(command) == false)
            throw new Error('Unable to find CommandHandler.');
    
        return map.get(command);
    }
    
        3
  •  0
  •   Andrey Golubov    5 年前

    interface Cmd<T = string> { _T: T  }
    interface CmdHandler<T = string> { _T: T }
    
    declare class CmdOne implements Cmd<'CmdOne'> { _T: 'CmdOne' }
    declare class CmdTwo implements Cmd<'CmdTwo'> { _T: 'CmdTwo' }
    declare class CmdThree implements Cmd<'CmdThree'> { _T: 'CmdThree' }
    
    declare class CmdHandlerOne implements CmdHandler<'CmdOne'> { _T: 'CmdOne' }
    declare class CmdHandlerTwo implements CmdHandler<'CmdTwo'> { _T: 'CmdTwo' }
    //declare class CmdHandlerThree implements CmdHandler<'CmdThree'> { _T: 'CmdThree' }
    
    const cmds = [
        [CmdOne, CmdHandlerOne],
        [CmdTwo, CmdHandlerTwo],
        //[CmdThree, CmdHandlerThree],
    ];
    
    export function CmdFactory<T>(cmd: Cmd<T>): CmdHandler<T> {
        const handle = cmds.find(pair => cmd instanceof pair[0])[1];
        return new handle as any; /// not good!
    }
    
    CmdFactory(new CmdOne)
    CmdFactory(new CmdThree) /// Need error
    
    

    playground