依賴注入方式比較:Constructor vs Inject

基本概念

  1. Constructor-based DI(建構函式注入):

import { UserService } from './user.service';

export class UserComponent {
  constructor(private userService: UserService) {}
}
  1. Inject-based DI(裝飾器注入):

import { inject } from '@angular/core';
import { UserService } from './user.service';

export class UserComponent {
  private userService = inject(UserService);
}

詳細比較

特性
Constructor-based
Inject-based

語法

在建構函式參數中宣告

使用 inject() 函數

可讀性

較高,一眼可見依賴

較分散,需要逐行查看

測試性

較容易測試,依賴明確

需要額外設置測試環境

使用場景

類別中固定的依賴

條件性注入、邏輯性注入

靈活性

較低,只能在建構函式中注入

較高,可在任何地方注入

TypeScript 支援

自動類型推斷

需要明確指定類型

使用場景示例

1. Constructor-based DI

適合用於:

  • 固定的服務依賴

  • 需要在建構時就確定的依賴

  • 需要良好測試性的組件

@Component({
  selector: 'app-user',
  template: `<div>{{ userName }}</div>`
})
export class UserComponent implements OnInit {
  userName = '';

  constructor(
    private userService: UserService,
    private authService: AuthService
  ) {}

  ngOnInit() {
    this.userName = this.userService.getUserName();
  }
}

2. Inject-based DI

適合用於:

  • 條件性注入

  • 延遲注入

  • 在類別屬性中直接注入

@Component({
  selector: 'app-user',
  template: `<div>{{ userName }}</div>`
})
export class UserComponent {
  private userService = inject(UserService);
  private authService = this.shouldUseAuth() 
    ? inject(AuthService) 
    : null;

  userName = this.userService.getUserName();

  private shouldUseAuth() {
    return someCondition;
  }
}

特殊使用場景

1. 條件性注入

export class FeatureComponent {
  private service = environment.production 
    ? inject(ProductionService)
    : inject(DevelopmentService);
}

2. 在裝飾器中使用

@Injectable({
  providedIn: 'root'
})
export class ConfigService {
  private http = inject(HttpClient);
  private config = inject(CONFIG_TOKEN);
}

3. 靜態屬性中使用

export class AppComponent {
  static service = inject(UserService);
}

使用時機

  1. 使用 Constructor-based DI 當:

    • 依賴是固定的

    • 需要良好的測試性

    • 程式碼需要高可讀性

  2. 使用 Inject-based DI 當:

    • 需要條件性注入

    • 在靜態內容中注入

    • 需要在特定邏輯下注入

Last updated