Python デザイン パターン: 23 のデザイン パターンの紹介

デザインパターンの背景

ソフトウェア開発の初期の頃、デザイナーやプログラマーは通常、自分自身の経験と直感に基づいてコードを作成しました。しかし、ソフトウェアのサイズと複雑さが増すにつれて、この書き方はますます難しくなります。そこでデザインパターンが生まれました。

デザインパターンはもともと、コードの保守性の低さ、再利用性の低さ、可読性の低さなど、開発初期のさまざまな問題を解決するために形成されました。デザイン パターンは、開発者が高品質のコードを記述する方法についてより体系的に考えることができる構造化された思考プロセスを提供します。

デザインパターンの歴史

デザイン パターンの歴史は、オブジェクト指向プログラミングの概念が普及した 1970 年代後半から 1980 年代初頭にまで遡ります。この時期、コンピューター科学者は、複雑なソフトウェア設計の問題に対処するより良い方法を見つけようと試み始めました。

最初にデザイン パターンを提案したのは、Simula 言語の創設者である Kristen Nygaard と Ole-Johan Dahl でした。Simula 言語は、オブジェクト指向プログラミングをサポートした最初の言語です。初期の Simula 言語では、設計パターンがすでに存在しており、いくつかの複雑なソフトウェア問題を解決するために使用されていました。

1994 年まで、4 人のコンピューター科学者、エリック ガンマ、リチャード ヘルム、ラルフ ジョンソン、ジョン ブリシデスは、「デザイン パターン: 再利用可能なオブジェクト指向ソフトウェアの基礎」という本を共同出版し、ソフトウェア エンジニアリングの分野にデザイン パターンの概念を正式に導入しました。 。

デザインパターンの誕生年と発明者

デザイン パターンの概念は、Kristen Nygaard と Ole-Johan Dahl によって最初に提案されましたが、最も広く流通している書籍は、「Gang of Four」(GoF) の著者による「Design Patterns: Fundamentals of Reusable Object-Oriented Software」です。 "この本。1994 年に出版されたこの本は、エリック ガンマ、リチャード ヘルム、ラルフ ジョンソン、ジョン ブリシデスの共著です。この本の影響が大きく、この 4 人の著者はデザインパターンの発明者としても知られています。

デザインパターンの歴史

1990 年代に誕生して以来、デザインパターンはソフトウェア開発の分野で徐々に重要な概念になってきました。ソフトウェア開発では、デザイン パターンは開発者がコードをより適切に整理し、コードの品質と再利用性を向上させるのに役立ちます。同時に、デザインパターンはオブジェクト指向の設計とプログラミングの中核概念の 1 つになりました。

デザイン パターンの開発には、いくつかの重要なマイルストーンがあります。その中でも最たるものが、GoF 著『Design Patterns: Fundamentals of Reusable Object-Oriented Software』という本です。本書では23のデザインパターンを初めて体系的にまとめ、分類して解説しています。さらに、デザイン パターンについて議論し拡張する書籍や記事が他にも数多くあり、デザイン パターンの開発と普及を促進しています。

デザイン パターンは、ソフトウェア開発における古典的な問題解決手法であり、作成パターン、構造パターン、動作パターンの 3 つのカテゴリに分類できる 23 のデザイン パターンが含まれています。

1.クリエーションモード

1.1 シングルトンモード

シングルトン パターンは、プログラム内に特定のクラスのインスタンスが 1 つだけ存在することを保証し、そのインスタンスへのグローバル アクセス ポイントを提供します。通常、スレッド プール、ネットワーク接続プールなどのリソースへのアクセスを制御するために使用されます。

実装原則: 唯一のインスタンスは静的変数を介して保存され、コンストラクターは外部インスタンス化を防ぐためにプライベートとして設定されます。

アプリケーション シナリオ: マルチスレッド、データベース操作、ロギングなど。

1.2 ファクトリーモード

ファクトリ パターンはオブジェクトを作成する方法であり、new 演算子の代わりにファクトリ メソッドを使用して必要なオブジェクトを作成します。対応するオブジェクトは、ファクトリに渡されたパラメータのタイプに基づいて動的に作成できます。

実装原則: 抽象ファクトリまたは具象ファクトリを通じてオブジェクトを作成するには、クライアントはファクトリ インターフェイスを知っているだけで済みます。

アプリケーション シナリオ: ポリモーフィズム、オブジェクト作成プロセスのシールド、コードの再利用率の向上。

1.3 抽象ファクトリーパターン

抽象ファクトリ パターンは、ファクトリ メソッド パターンと同様の設計パターンであり、どちらもオブジェクトの作成に使用されます。抽象ファクトリ パターンとファクトリ メソッド パターンの違いは、オブジェクトを作成できるだけでなく、オブジェクトのグループも作成できることです。

実装原則: 抽象ファクトリ クラスを使用して、ファクトリがサポートする必要があるメソッドのセットを定義し、特定のファクトリがこれらのメソッドを実装して特定の製品を作成します。

アプリケーション シナリオ: ポリモーフィズム、オブジェクト作成プロセスのシールド、コードの再利用率の向上。

1.4 ビルダーモード

ビルダー パターンは、複雑なオブジェクトの構築プロセスをその表現から分離するため、同じ構築プロセスで異なる表現オブジェクトを作成できます。このパターンは、さまざまなプロパティを持つオブジェクトを作成するためによく使用されます。

実装原則: Builder クラスと一連の Director クラスを定義して、Builder クラスの呼び出しシーケンスの一部をカプセル化します。Client クラスは、特定の呼び出しシーケンスを実装するために、対応する Director を指定する責任があります。

アプリケーション シナリオ: 複雑なオブジェクトまたは構成可能なオブジェクトを作成します。

1.5 試作パターン

プロトタイプ パターンは、指定されたプロトタイプ インスタンスから新しいインスタンスをコピーします。これは、新しいオブジェクトの作成時にコストがかかる場合、またはコンストラクターに複雑な依存関係がある場合に適しています。

実装原則: 抽象親クラスを定義し、オブジェクトをコピーする Clone メソッドを実装します。サブクラスは Clone メソッドをオーバーライドして、サブクラス オブジェクトを返します。

アプリケーション シナリオ: 複雑なオブジェクトを生成し、コンストラクターの初期化のオーバーヘッドを回避します。

2. 構造パターン

2.1 アダプターモード

アダプター パターンは、あるクラスのインターフェイスを、クライアントが期待する別のインターフェイスに変換します。アダプターを使用すると、互換性のないクラスが連携して動作できるようになります。

実装原則: アダプター クラスを使用して、クラスのインターフェイスを顧客が必要とするインターフェイスに変換します。

アプリケーション シナリオ: インターフェイスを変更せずに既存のクラスを使用し、互換性のないインターフェイス間の問題を解決します。

2.2 デコレータパターン

デコレータ パターンは、オブジェクトに責任を動的に割り当て、実際のオブジェクトをデコレータ オブジェクトでラップすることによってオブジェクトの機能を拡張します。

実装原則: 抽象クラスを使用して装飾する必要があるオブジェクトを定義し、装飾クラスを使用して抽象クラスを継承し、その中のメソッドを書き換え、メソッドの呼び出しの前後に必要な操作を追加します。

アプリケーション シナリオ: オブジェクトを動的に拡張し、オブジェクトの機能を強化し、過度に複雑な継承関係を回避します。

2.3 コンビネーションモード

複合モードでは、オブジェクトをツリー構造に構成して「全体」階層を表現し、ユーザーが単一オブジェクトと複合オブジェクトを一貫した方法で使用できるようにします。

実装原則: 抽象クラスを使用してオブジェクトとその動作を定義し、具象クラスを使用してさまざまなタイプのオブジェクトを実装します。

アプリケーション シナリオ: ツリー構造、再帰的構造、固定階層。

2.4 外観モード

ファサード モードは、サブシステム内のインターフェイスのグループにアクセスするための統合インターフェイスを提供します。これは、サブシステムを使いやすくする高レベルのインターフェイスを定義します。

実装原則: ファサード クラスを使用して、他のクラスの複雑な操作をカプセル化します。

アプリケーション シナリオ: システムを分離し、システム コール プロセスを簡素化します。

2.5 プロキシモード

プロキシ パターンは、元のコードを変更せずに動作を追加します。プロキシ オブジェクトとプロキシ オブジェクトは共通のインターフェイスを持ち、プロキシ オブジェクトは実際のオブジェクトにアクセスする方法を知っており、実際のオブジェクトのアクセスを制御できます。

実装原則: プロキシ クラスを使用して、プロキシする必要があるクラスをラップし、クライアントが使用する同じインターフェイスを公開します。

アプリケーション シナリオ: ターゲット オブジェクトの保護、追加のアクセス制御の提供、遅延初期化、データのキャッシュなど。

3. 行動パターン

3.1 オブザーバーパターン

Observer パターンは、オブジェクト間の 1 対多の依存関係を定義するため、オブジェクトの状態が変化するたびに、関連する依存オブジェクトが通知され、自動的に更新されます。

実装原則: オブザーバー インターフェイスを使用してオブザーバーと対応する通知メソッドを定義します。特定のオブザーバーはこのインターフェイスを実装する必要があります。監視対象のオブジェクトはオブザーバーのリストを維持し、状態が変化したときにオブザーバーに通知する必要があります。

アプリケーション シナリオ: メッセージ受け渡し、ステータス更新、イベント処理など。

3.2 戦略パターン

Strategy パターンは、概念的にはすべて同じ仕事を実行するアルゴリズムのファミリーを定義する方法であり、実装方法が異なるだけです。

実装原則: 抽象クラスまたはインターフェイスを使用してアルゴリズムを定義し、具象クラスを使用してさまざまなアルゴリズムを実装します。

アプリケーション シナリオ: 実行時にアルゴリズムを動的に選択する必要がある場合に使用する必要があります。

3.3 テンプレートメソッドのパターン

テンプレート メソッド パターンは、操作のアルゴリズムのスケルトンを定義し、一部のステップをサブクラスでの実装に延期します。これは継承ベースの設計パターンです。

実装原則: 抽象クラスまたはインターフェイスを使用してアルゴリズムのスケルトンを定義し、具象クラスを使用して特定のステップを実装します。

アプリケーション シナリオ: 固定アルゴリズム フレームワーク、コードの再利用。

3.4 イテレータパターン

Iterator パターンは、オブジェクトの内部表現を公開せずに、コンテナ オブジェクト内の個々の要素にアクセスする方法を提供します。

実装原則: イテレータ クラスを使用してコンテナ オブジェクトをカプセル化し、さまざまな反復メソッドを実現します。

アプリケーション シナリオ: コンテナ オブジェクトを走査または検索するときに使用されます。

3.5 コマンドモード

コマンド パターンはリクエストをオブジェクトとしてカプセル化し、さまざまなリクエストでクライアントをパラメータ化できるようにします。同時に、リクエストをキューに入れ、リクエスト ログを記録し、元に戻す操作をサポートすることができます。

実装原則: コマンド インターフェイスを使用してコマンド操作を定義し、特定のクラスを使用して特定のコマンド操作を実装します。

アプリケーション シナリオ: リクエスト ログの記録、元に戻す操作のサポート、複数のコマンドの実行のサポートなどが必要です。

上記は 23 のデザイン パターンの導入と実装の原則であり、シナリオが異なれば、問題を解決するために異なるデザイン パターンが必要になります。開発者は、状況に応じて適切なデザインパターンを選択し、実際の開発で柔軟に活用する必要があります。後ほど、Python を使用して各デザインパターンを詳しく紹介します。

おすすめ

転載: blog.csdn.net/weixin_40025666/article/details/131221448