技術共有

ソフトウェア設計パターンの概要

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

設計パターンは、ソフトウェア設計における一般的な問題に対する一般的な解決策です。以下に、一般的なデザイン パターンをいくつか示します。これらは、作成パターン、構造パターン、動作パターンの 3 つの主要なカテゴリに分類されます。

創作パターン

これらのパターンはオブジェクト作成のメカニズムを提供し、既存のコードの柔軟性と再利用性を高めます。

  1. シングルトンパターン

    • クラスのインスタンスが 1 つだけであることを確認し、グローバル アクセス ポイントを提供します。
  2. ファクトリメソッドパターン

    • オブジェクトを作成するためのインターフェイスを定義し、どのクラスをインスタンス化するかをサブクラスに決定させます。
  3. 抽象ファクトリー パターン (抽象ファクトリー)

    • 具体的なクラスを明示的に指定せずに、関連オブジェクトまたは依存オブジェクトのファミリーを作成します。
  4. ビルダーパターン(ビルダー)

    • 複雑なオブジェクトを構築し、段階的に構築できます。
  5. プロトタイプ

    • 新しいインスタンスを作成するのではなく、既存のインスタンスをコピーして新しいインスタンスを作成します。

構造パターン

これらのパターンは、オブジェクトの組み合わせ、またはオブジェクトとオブジェクト間の関係を扱います。

  1. アダプターモード

    • オブジェクト間のインターフェースの非互換性を「アダプター」を通じて解決できるようにします。
  2. デコレータパターン(デコレータ)

    • 追加の責任をオブジェクトに動的に追加します。
  3. プロキシモード(プロキシ)

    • 別のオブジェクトへのアクセスを制御するための代替またはプレースホルダーを提供します。
  4. ファサード

    • サブシステム内のインターフェイスのグループにアクセスするための統合された高レベルのインターフェイスを提供します。
  5. ブリッジモード(ブリッジ)

    • 抽象部分をその実装から分離して、独立して変更できるようにします。
  6. 複合モード

    • オブジェクトをツリー構造にグループ化して、部分と全体の階層を表します。
  7. フライウェイトモード

    • 共有を通じて、多数のきめの細かいオブジェクトを効率的にサポートします。

行動パターン

これらのパターンは、オブジェクト間の通信、つまりオブジェクトがどのように相互作用し、責任を分散するかに焦点を当てています。

  1. 戦略

    • 一連のアルゴリズムを定義し、それらを 1 つずつカプセル化し、交換可能にします。
  2. テンプレートメソッドパターン(テンプレートメソッド)

    • メソッド内でアルゴリズムのフレームワークを定義し、実装をサブクラスに延期します。
  3. オブザーバーパターン(オブザーバー)

    • オブジェクト間の 1 対多の依存関係。オブジェクトの状態が変化すると、そのオブジェクトに依存するすべてのオブジェクトが通知され、自動的に更新されます。
  4. イテレータパターン(イテレータ)

    • 内部表現を公開せずに、集合オブジェクト内の個々の要素に順次アクセスします。
  5. 責任連鎖モデル

    • 複数のオブジェクトにリクエストを処理する機会を与えることで、リクエストの送信者と受信者の結合を回避します。
  6. コマンドモード(コマンド)

    • リクエストをオブジェクトとしてカプセル化し、ユーザーがさまざまなリクエストでクライアントをパラメータ化できるようにします。
  7. メメントモード

    • オブジェクトの内部状態をキャプチャし、カプセル化を壊さずにこの状態をオブジェクトの外部に保存します。
  8. ステートモード

    • オブジェクトの内部状態が変化したときに、オブジェクトの動作を変更できるようにします。
  9. ビジターモード

    • オブジェクト構造 (複合構造など) に新しい機能を追加します。
  10. メディエーターパターン

    • 中間オブジェクトを定義して、元のオブジェクト間の対話を簡素化します。
  11. 通訳モード(通訳)

    • 言語の文法表現を定義し、その言語で定義された文を解釈します。

前回のインタビューでは、コードを使用してサブスクライバーとパブリッシャーのパターンを実装することについて質問されました。時間があったので、これらの設計パターンを JS コードでシミュレートしました。

例えば

class PubSub {
  constructor() {
    this.events = {}; // 存储事件名称和对应的订阅者回调函数数组
  }

  // 订阅事件
  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []; // 如果事件不存在,初始化一个空数组
    }
    this.events[event].push(callback); // 将回调函数添加到订阅者的数组
  }

  // 取消订阅事件
  unsubscribe(event, callback) {
    if (!this.events[event]) {
      return;
    }
    this.events[event] = this.events[event].filter(cb => cb !== callback); // 移除指定的回调函数
  }

  // 取消特定事件的所有订阅
  unsubscribeAll(event) {
    if (this.events[event]) {
      delete this.events[event]; // 删除所有订阅者
    }
  }

  // 触发事件,使用 emit 作为方法名
  emit(event, data) {
    if (this.events[event]) {
      // 执行所有订阅者的回调函数
      this.events[event].forEach(callback => callback(data));
    }
  }

  // 检查是否有订阅者
  hasSubscribers(event) {
    return this.events[event] && this.events[event].length > 0;
  }
}

// 使用示例
const eventCenter = new PubSub();

// 订阅 'message' 事件
eventCenter.subscribe('message', (data) => {
  console.log(`Message received: ${data}`);
});

// 订阅 'greet' 事件
eventCenter.subscribe('greet', (name) => {
  console.log(`Hello, ${name}!`);
});

// 触发 'message' 事件
eventCenter.emit('message', 'Hello, Pub/Sub!');

// 触发 'greet' 事件
eventCenter.emit('greet', 'World');

// 取消对 'message' 事件的订阅
const myCallback = (data) => {
  console.log(`My callback received: ${data}`);
};
eventCenter.subscribe('message', myCallback);
eventCenter.unsubscribe('message', myCallback);

// 再次触发 'message' 事件,myCallback 不会被调用
eventCenter.emit('message', 'This message will not be received by myCallback');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

この例では、PubSub このクラスは次の機能を提供します。

  • subscribe このメソッドを使用すると、サブスクライバーは特定のイベントにコールバック関数を登録できます。
  • unsubscribe このメソッドを使用すると、サブスクライバーは特定のイベントからコールバック関数の登録を解除できます。
  • unsubscribeAll メソッドは、特定のイベントへのすべてのサブスクリプションをキャンセルします。
  • emit このメソッドはイベントをトリガーし、すべてのサブスクライバーのコールバック関数を実行します。
  • hasSubscribers メソッドは、特定のイベントのサブスクライバーが存在するかどうかを確認します。