Table of Contents
3つのコアクリエイティカルパターンを理解する
ソフトウェア設計パターンは、再発設計の問題を解決するための戦いテストされた青写真です。最も頻繁に使用されるのは、オブジェクトがインスタンス化される方法を制御する作成パターンです。正しいものを選ぶと、コードの保守性、パフォーマンス、スケーラビリティに直接影響します。この拡張ガイドは、各パターンに深く飛び込み、実際のシナリオを探索し、通知された決定を行うのに役立つ実用的な基準を提供します。
単トンパターン: ルールのテーマへの1つのインスタンス すべて
シングルトンパターンは、クラスが正確にインスタンスを1つ確保し、グローバルアクセスポイントを付与します。最もシンプルなパターンの1つであり、誤用されることが多いです。コアの考え方は、クラスのリクエスト回数に関係なく、同じオブジェクトが返されるように、インスタンス化プロセスを制御することです。
シングルトンの仕組み
一般的に、シングルトンクラスはプライベートコンストラクタとインスタンスを返す静的なメソッドを持っています。最初の呼び出しはオブジェクトを作成します。その後、同じインスタンスを再利用します。マルチスレッド環境では、複数のインスタンスを作成できるレース条件を防ぐための同期が必要です。
public class DatabaseConnectionPool {
private static DatabaseConnectionPool instance;
private DatabaseConnectionPool() { /* initialization */ }
public static synchronized DatabaseConnectionPool getInstance() {
if (instance == null) {
instance = new DatabaseConnectionPool();
}
return instance;
}
}
シングルトンの輝き
- ]共有リソースの管理:[]]]接続プール、ロギングサービス、または構成マネージャは、単一のコオリンジのポイントから恩恵を受けます。
- [グローバル状態:]]]アプリケーション全体のキャッシュまたはレジストリが一貫したアクセスを必要とするとき。
- []ハードウェアまたはOSレベルのリソース:[[ファイルシステム、プリンタスプール、またはウィンドウマネージャは、通常、1つのインスタンスのみを許可します。
避けるべき一般的な落札
- [:]] すべてをシングルトンで使用することで、隠し依存関係につながり、モックでインスタンスを簡単に交換できないため、ユニットテストが難しくなります。
- []3つの安全上頭:[古典的な同期方法は、ボトルネックになることができます。 エイジャーの初期化やダブルチェックロック(揮発性)などの代替は、分泌を低下させます。
- Tight カップリング:]]]] グローバルなアクセスポイントがハード コード化されているため、クライアントは、依存性反転原理を違反して、コンクリートシングルトンクラスに結合されます。
これらの欠点にもかかわらず、シングルトンは、真にシングル、グローバルアクセス可能なオブジェクトを必要とするときに便利です。 より深い理解のために、 ]を参照してください。 グルのシングルトンガイドを修復します。
工場パターン:オブジェクト作成の委任
ファクトリーパターンは、オブジェクトのインスタンス化ロジックをカプセル化し、サブクラスがどのクラスをインスタンス化するかを決定できるようにします。これは、2つの主なフレーバーに来ます。Factory Method(新しいオブジェクトを返す単一のメソッド)と[Abstract Factory](関連ファクトリーメソッドの家族)。両方のは、コンクリートクラスからクライアントコードを分離し、緩やかなカップリングと拡張性を促進します。
工場方法の詳細
オブジェクトを作成するためのインターフェイスを定義しますが、サブクラスは生成されるオブジェクトの種類を変更してみましょう。例えば、ダイアログクラスはメソッドを持つかもしれません。WindowsDialogやLinuxDialogのようなサブクラスは、このメソッドをオーバーライドしてプラットフォーム固有のボタンを返すようにします。
abstract class Dialog {
abstract Button createButton();
public void render() {
Button okButton = createButton();
okButton.onClick();
}
}
class WindowsDialog extends Dialog {
Button createButton() { return new WindowsButton(); }
}
このパターンは、次の場合に理想的です。
- クラスは、オブジェクトのクラスを生成してはならない。
- オブジェクト作成ロジックを1つの場所にローカライズしたい。
- システムは、そのオブジェクトが構築される方法とは独立する必要があります。
抽象工場:関連オブジェクトの家族を生産
Abstract Factoryは、具体的なクラスを指定せずに、関連オブジェクトや依存オブジェクトの家族を作成するためのインターフェイスを提供します。 特定のテーマ(例、材料、Cuertino)で一貫した外観を、ボタン、チェックボックス、スクロールバーを生成しなければならないGUIツールキットを考えます。 クライアントは、抽象的なファクトリーインターフェイスを使用して、製品を入手し、具体的な工場(MaterialFactory、CuertinoFactory)は正しい変形を生成します。
このパターンは、次の場合に優先されます。
- 複数の家族が複数の製品群で構成する必要があります。
- 製品の一貫性を強化したい。
- 新製品の家族を追加することで、既存のコードに最小限の変更が必要となる。
工場とその他のパターンの決定
オブジェクトの作成が複雑であるか、実行時に実装を交換する必要がある場合は、工場は、Go-toです。インスタンス数を制限しないため、単トンよりも柔軟です。それは作成を一元化します。プロトタイプとは異なり、工場は既存のものをコピーするのではなく、新しいインスタンスをゼロから作成します。両方のバリアントの包括的な概要については、]を参照してください。Guruの工場方法ページとのページをリファクタリングします。[FLT:]と[FLT:[FLT:]:[FLT:]工場]を参照してください。
プロトタイプ パターン: 構造物の代りのクローン
Prototype パターンは、既存のオブジェクトをコピーして新しいオブジェクトを作成します。プロトタイプ。インスタンス化が高価(重データベースのクエリ、複雑な幾何学の計算など)、またはオブジェクト構成が時間がかかります。ゼロからビルドする代わりに、あらかじめ設定されたインスタンスをクローンし、必要に応じて調整します。
電化メカニック:シャロー対ディープコピー
ほとんどのプログラミング言語は、Java の組み込みクローンメソッド ()、Python の [] 、または JavaScript でスプレッド () を提供します。ただし、コピーが浅いかどうか (ミュータブルオブジェクトへの共有参照) または深く (十分に独立した) に注意を払わなければなりません。深いコピーは、クローンによって参照されるすべてのオブジェクトを複製します。プロトタイプを実装するとき、あなたは、あなたのケースに合ったコピーレベルを決定する必要があります。
class MazePrototype {
public MazePrototype clone() throws CloneNotSupportedException {
return (MazePrototype) super.clone(); // shallow copy
}
}
プロトタイプのための理想的なシナリオ
- Costly オブジェクト作成:] たとえば、ファイルから大きな構成をロードしたり、複雑な幾何学メッシュを生成したりします。
- []動的ランタイムオブジェクト:[]。システムがランタイムで決定される新しいオブジェクトを生成しなければならないとき(例えば、あらかじめ定義されたテンプレートからスポーンされたゲーム内の敵タイプ)。
- サブクラスの爆発を削減:[ではなく、わずかな変動のための多くのサブクラスを作成して、プロトタイプをクローンし、いくつかのプロパティを調整します。
プロトタイプレジストリとキャッシュ
Prototype は、レジストリを実装することで、キーによって索引付けされたプレビルドされたプロトタイプの中央店である。クライアントは、プロトタイプをキーでリクエストし、それをクローン化し、それをカスタマイズすることができます。レジストリと Prototype のこの組み合わせは、特定のケースでファクトリーまたはシングルトンの代替として機能することができます。詳細なウォークスルーについては、]を参照してください。Guru のプロトタイプガイドを改造する。
サイドバイサイド比較:シングルトン、工場、プロトタイプ
選択するのに、下の表は、重要な違いを強調します。
| Pattern | Instance Count | Creation Mechanism | Best For |
|---|---|---|---|
| Singleton | Exactly one | Self-managed global access | Shared resources, global state |
| Factory | Multiple instances (or families) | Centralized creation logic | Decoupling client from concrete classes, complex creation |
| Prototype | Multiple instances cloned from a template | Cloning (shallow/deep copy) | Expensive instantiation, runtime object generation |
パターンが重なり、または結合するとき
- [単トン+工場:[]]])工場は、単トン(例えば、1プラットフォームあたりの抽象的な工場)であることができます。 これは、集中的な作成とグローバルアクセスを組み合わせます。
- [プロトタイプ+ファクトリー:[]]]プロトタイプレジストリは、コンストラクタを呼び出す代わりに、工場として機能することができます。 これは、企業をスポーンするときにゲーム開発で特に便利です。
- [プロトタイプ+シングルトン:[]]プロトタイプオブジェクトは、クローンが単トンではなく、タイプごとに1つのプロトタイプインスタンスが存在するという感覚で単トンになるかもしれません。
実用的な意思決定フレームワーク
作成パターンを呼び出すデザイン問題に直面した場合、次の質問をしてください。
- []アプリケーション全体で正確に1つのインスタンスが必要ですか?[])。 もしそうなら、シングルトンを検討してください。 しかし、グローバルに共有された状態が本物的に必要であり、そのテスト可能性は苦しむことはありません。
- []オブジェクト作成コンプレックスですか、変更する可能性はありますか?[])はいの場合、ファクトリーメソッドまたはアブストラクトファクトリーを使用します。新しいオブジェクトタイプを追加しようとすると、これは特に役立ちます。
- [] オブジェクトは、パフォーマンスボトルネックを作成するか、少しだけ異なる多くのインスタンスが必要ですか?]])。 場合、プロトタイプはテンプレートをクローンすることで時間とメモリを節約できます。
- [1パターン以上が同じ目的に機能することはできますか?[]] 取引オフを評価します。例えば、目標が不変なデータを共有している場合、FlyweightパターンはPrototypeの代わりにメモリを低下させる可能性があります。
エンジニアリングソフトウェアの実世界例
エンジニアリングアプリケーションは、これらのパターンをよくブレンドします。CADシステムでは、ユーザー設定マネージャ、工場が複雑なアセンブリをクローニングし、それを変更するためのさまざまな幾何学的形状(円、ポリゴン、スプライン)、およびPrototypeを作成するためのユーザー設定マネージャ用の単トンを使用する場合があります。シミュレーションエンジンは、さまざまなソルバーオブジェクトを作成するために工場を採用することができ、パーティクルシステム構成をコピーするためのプロトタイプ、すべてのシミュレーション手順を記録するロギングサービス用の単トン。
結論: パターンをあなたの設計をわかせるようにしないでください
シングルトン、工場、およびプロトタイプは基礎的な創造パターンですが、彼らは銀製の弾丸ではありません。最良の選択は、システムの制約を理解することから現れます。例えば制御の必要性、オブジェクトの作成の複雑性、および新しいインスタンスのコスト。常に明快さとパターン純度に対するテスト性を好む。疑わしいとき、ファクトリーで開始 - それは最もクリーンな装飾を提供し、後で状況が保証されるならば、プロトタイプまたはシングルトンに交換または拡張することができます。
これらの3つのパターンをマスターすることで、堅牢で柔軟なエンジニアリングソフトウェアを構築するための汎用性の高いツールキットを自分で装備します。さらに、読み物については、ソフトウェア設計パターンとに関するWikipediaの記事を調べます。