2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるパターン設計:Observer・Factory・Strategyなどの現代的応用戦略

Posted at

概要

パターンとは「コードに名前を与え、設計の意図を共有する技術」である。
JavaScriptにおいても、デザインパターンは構造・振る舞い・生成方法を明示化するための設計言語として機能する。

本稿では、実用性が高く現代JSにも適した5つのパターンを解説する:

  • Observer(監視者)
  • Factory(生成)
  • Strategy(戦略)
  • Singleton(単一性)
  • Command(命令オブジェクト)

1. Observer パターン:変化の伝播

✅ 使いどころ:状態変化の通知、多対多の依存関係

class Subject {
  constructor() {
    this.observers = [];
  }

  subscribe(fn) {
    this.observers.push(fn);
  }

  notify(data) {
    this.observers.forEach(fn => fn(data));
  }
}

// 利用例
const store = new Subject();

store.subscribe((val) => console.log('変更検知:', val));
store.notify({ count: 1 });

→ ✅ 状態の変化を購読させ、疎結合でリアクティブな構造を実現


2. Factory パターン:生成の抽象化

✅ 使いどころ:条件によって異なるインスタンス生成、newの隠蔽

function createUser(role) {
  if (role === 'admin') {
    return { role, permissions: ['ALL'] };
  } else {
    return { role, permissions: ['READ'] };
  }
}

const admin = createUser('admin');

→ ✅ インスタンス生成ロジックを隠蔽し、呼び出し側の責務を軽減


3. Strategy パターン:振る舞いの切り替え

✅ 使いどころ:アルゴリズムを切り替え可能にする

class Sorter {
  constructor(strategy) {
    this.strategy = strategy;
  }

  sort(arr) {
    return this.strategy(arr);
  }
}

const bubbleSort = arr => [...arr].sort();
const quickSort = arr => [...arr].sort((a, b) => a - b);

const sorter = new Sorter(quickSort);
console.log(sorter.sort([3, 1, 2]));

→ ✅ アルゴリズムを関数として外部化し、再利用性と切替性を確保


4. Singleton パターン:インスタンスの一意性保証

✅ 使いどころ:状態を共有したいがインスタンスは1つでいいとき

const Logger = (() => {
  let instance;

  function create() {
    return { log: (msg) => console.log('[Log]', msg) };
  }

  return {
    getInstance: () => {
      if (!instance) instance = create();
      return instance;
    }
  };
})();

Logger.getInstance().log('初回');
Logger.getInstance().log('同じインスタンス');

→ ✅ アプリケーションスコープでの状態共有やキャッシュに最適


5. Command パターン:処理の抽象化・遅延実行

✅ 使いどころ:操作を“オブジェクト”として定義し、キュー制御やUndoを可能に

class Command {
  constructor(execute, undo) {
    this.execute = execute;
    this.undo = undo;
  }
}

const queue = [];

function runCommand(cmd) {
  cmd.execute();
  queue.push(cmd);
}

function undoLast() {
  const cmd = queue.pop();
  if (cmd) cmd.undo();
}

// 使用例
const logCmd = new Command(
  () => console.log('実行'),
  () => console.log('取り消し')
);

runCommand(logCmd); // 実行
undoLast();         // 取り消し

→ ✅ 処理の“記録・再生・取り消し”が可能に


パターン適用判断フロー

① 状態変化を通知したい? → Observer

② 条件で生成物が変わる? → Factory

③ アルゴリズムを切り替えたい? → Strategy

④ インスタンスを1つに制限したい? → Singleton

⑤ 実行ロジックを外部化したい? → Command

よくあるミスと対策

❌ パターンを使うことが目的化している

→ ✅ パターンは“構造を整理するための手段”である
→ “自作パターン”が必要なこともある


❌ 密結合な構成のままObserverを導入

→ ✅ 発火元と購読者を完全に疎結合に設計


❌ 使い捨てコードにSingletonを導入

→ ✅ 永続性・共有性がある前提のときだけ使う


結語

パターンとは、設計の言語である。
ただの構文やテクニックではなく、“どう構造を分けるか”という思想をコードに落とすための手段である。

  • Observerは伝える
  • Factoryは隠す
  • Strategyは選ばせる
  • Singletonは統一する
  • Commandは委ねる

設計は、ただ正しく書くのではなく、“正しく分ける”ことで生まれる。
パターンはその分け方を支える、コード設計の言語である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?