Angular開発メモ

調べたことを記録しておきます。

【Angular】Angularでよく使われるデザインパターン7選【設計力アップ】

Angularのアプリケーションを設計していると、「処理を切り替えたい」「サービスを共通化したい」「RxJSをもっと上手く使いたい」といった悩みが出てきませんか?

そういったときに役立つのが「デザインパターン(設計パターン)」です。

この記事では、Angularでよく使われる7つのデザインパターンを紹介します。現場でもよく使われるパターンばかりなので、実装の引き出しを増やしたい方はぜひ参考にしてください。


Strategy Pattern(ストラテジーパターン)

  • 目的:処理(戦略)を動的に切り替える
  • 使いどころ:フォームのプレースホルダーやバリデーションを条件ごとに切り替える
export interface PlaceholderStrategy {
  getPlaceholder(): string;
}

@Injectable()
export class AdminPlaceholderStrategy implements PlaceholderStrategy {
  getPlaceholder() {
    return '管理者用プレースホルダー';
  }
}

コンポーネント側では PlaceholderStrategy をDIで受け取り、戦略の中身を差し替えることで処理を切り替えます。

✅ なぜこれが「デザインパターン」なのか?

デザインパターンとは「再利用可能な設計上の知恵(設計指針)」であり、特定の実装言語や技術に依存しません。 Angularであっても、意図的に戦略(アルゴリズムや処理)を切り替える設計をしている時点で、それは「ストラテジーパターン」と呼ぶことができます。

そのため、「AngularでDIを活用して戦略を差し替えている構成」はまさにこのパターンの応用例です。


Singleton Pattern(シングルトンパターン)

  • 目的インスタンスを1つに固定してアプリ全体で共有
  • 使いどころ:認証状態や共通の設定情報など
@Injectable({ providedIn: 'root' })
export class AuthService {
  private token = '';
}

Angularのサービスは providedIn: 'root' によって自動的にシングルトンになります。


Factory Pattern(ファクトリーパターン)

  • 目的インスタンスの生成を外部の関数に委ねる
  • 使いどころ環境変数によって異なるサービスを返す場合など
export function configFactory(): ConfigService {
  return new ConfigService(environment.production);
}

providers: [
  { provide: ConfigService, useFactory: configFactory }
]

状況に応じて返すサービスを変えられるので、テストや環境ごとの切り替えに便利です。


Observer Pattern(オブザーバーパターン)

  • 目的:状態の変化を監視・通知する
  • 使いどころ:状態管理、非同期イベント、フォームの変化監視など
private subject = new Subject<string>();

notify(message: string) {
  this.subject.next(message);
}

get messages$(): Observable<string> {
  return this.subject.asObservable();
}

RxJSを使うことでオブザーバーパターンを自然に導入できます。


Facade Pattern(ファサードパターン)

  • 目的:複雑な処理をまとめて、簡単な窓口(API)を提供する
  • 使いどころ:複数のサービスを統合してコンポーネントに提供する場合
@Injectable()
export class UserFacade {
  constructor(
    private authService: AuthService,
    private userService: UserService
  ) {}

  loadUser() {
    if (this.authService.isAuthenticated()) {
      return this.userService.getUser();
    }
    return of(null);
  }
}

コンポーネント側の依存が減ることで、テストや保守がしやすくなります。


Dependency Injection(依存性注入パターン)

  • 目的:依存オブジェクトを外部から注入して柔軟性を高める
  • 使いどころ:Angularの全てのサービス設計
constructor(private userService: UserService) {}

Angular自体がこのパターンをベースに成り立っています。DIを正しく理解すると、モジュール設計が楽になります。


Command Pattern(コマンドパターン)

  • 目的:処理をオブジェクトとして抽象化し、実行履歴や取り消しを管理
  • 使いどころ:複雑なアクション処理、履歴管理、Undo処理など
interface Command {
  execute(): void;
}

class SaveCommand implements Command {
  constructor(private service: DataService) {}
  execute() {
    this.service.save();
  }
}

Angularでコマンドパターンを使う場面は限られますが、処理を疎結合に保ちたいときには有効です。


まとめ:パターン一覧

パターン名 主な用途 使いどころ例
Strategy Pattern 処理の切替を柔軟に フォームの入力や表示ロジックなど
Singleton Pattern インスタンスを1つに固定 サービス、設定、状態管理
Factory Pattern インスタンスの生成を外部に任せる 環境ごとのサービス切り替え
Observer Pattern 状態変化の購読と通知 RxJSによる状態管理
Facade Pattern 複雑な処理を簡単な窓口にまとめる コンポーネントとサービスの橋渡し
Dependency Injection 柔軟でテストしやすい設計を実現 全サービス、コンポーネント設計
Command Pattern 処理をオブジェクト化して履歴や再実行可能に 複雑なビジネスロジックや履歴処理

おわりに

Angularのような大規模フレームワークでは、デザインパターンを理解しておくことで設計の引き出しが格段に広がります。

パターンを知っていると「なぜこの構造なのか」「この処理はどこに分離すべきか」といった判断も速くなり、保守性・テスト性の高いコードが書けるようになります。

現場での実践にもぜひ活かしてみてください!