You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中按需动态创建服务的全新实例?

解决方案:在Angular中动态创建Command实例实现撤销/重做

核心思路

要实现运行时(如按钮点击)动态创建带依赖注入的Command实例,不能直接用new(无法自动注入依赖),也不能用Injector.get()(返回单例)。可以通过创建子注入器的方式,每次生成全新的Command实例,同时保留依赖注入能力。

步骤1:实现Command工厂服务

这个工厂负责创建Command的新实例,利用Angular的Injector创建子注入器来确保每次都是新实例:

import { Injectable, Injector, Type } from '@angular/core';
import { Command } from './command.interface'; // 假设你有Command基类/接口

@Injectable({ providedIn: 'root' })
export class CommandFactory {
  constructor(private injector: Injector) {}

  // 泛型方法,支持创建任意Command子类的实例
  createCommand<T extends Command>(commandType: Type<T>): T {
    // 创建子注入器,继承父注入器的所有依赖
    const childInjector = Injector.create({
      providers: [{ provide: commandType }],
      parent: this.injector
    });
    
    // 从子注入器获取新实例
    return childInjector.get(commandType);
  }
}

步骤2:定义你的Command类

修正原示例中的语法错误:

import { Injectable } from '@angular/core';
import { Command } from './command.interface';
import { SomeService } from './some.service';

@Injectable()
export class MyCommand extends Command {
  constructor(private someService: SomeService) {
    super(); // 如果Command是抽象类,记得调用父类构造函数
  }

  public execute(): void {
    const value = this.someService.getSomeValue();
    // 执行具体命令逻辑
  }

  // 实现撤销逻辑(Command模式必备)
  public undo(): void {
    // 撤销execute执行的操作
  }
}

步骤3:在组件中按需创建实例

在按钮点击等交互场景下,调用工厂创建新实例,并保存到历史记录用于撤销/重做:

import { Component } from '@angular/core';
import { CommandFactory } from './command.factory';
import { MyCommand } from './my.command';
import { Command } from './command.interface';

@Component({
  selector: 'app-my-component',
  template: `
    <button (click)="onExecuteCommand()">执行命令</button>
    <button (click)="onUndo()" [disabled]="commandHistory.length === 0">撤销</button>
  `
})
export class MyComponent {
  private commandHistory: Command[] = [];

  constructor(private commandFactory: CommandFactory) {}

  onExecuteCommand(): void {
    // 动态创建新的MyCommand实例
    const command = this.commandFactory.createCommand(MyCommand);
    command.execute();
    // 保存到历史记录
    this.commandHistory.push(command);
  }

  onUndo(): void {
    const lastCommand = this.commandHistory.pop();
    if (lastCommand) {
      lastCommand.undo();
    }
  }
}

方案适配性说明

  • 完全避开Injector.get()的单例问题,每次调用createCommand都会生成全新的实例
  • 实例在交互触发时动态创建,而非组件初始化阶段
  • Command类能正常注入Angular服务(如示例中的SomeService),满足依赖注入需求
  • 无需依赖transient providers,完全由业务逻辑控制实例创建时机

内容的提问来源于stack exchange,提问作者Matthew Holmes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:14:53