Table of Contents
クリエーションデザインパターンの紹介
クリエーションデザインパターンは、そのオブジェクトが作成、構成、および表現方法とは独立してシステムを作る、インスタンス化プロセスを抽象化します。GoFパターンの中で、シングルトンとファクトリーメソッドは最も頻繁に遭遇する2つですが、それらは根本的に異なる問題を解決します。単調はインスタンス数を制御しますが、ファクトリーメソッドは、どのコンクリートクラスをインスタンス化するかを選択する責任を委任します。どちらのパターンを緩和するかは、硬質でテストされたコードまたは不要な複雑さにつながる。この記事は、各パターンを指示するごとに、各パターンを調べます。
シングルトンパターンの詳細
シングルトンパターンは、クラスを単一インスタンスに制限し、そのインスタンスへのアクセスのグローバルポイントを提供します。それは最も簡単なパターンの1つであり、また、テスト可能性とカップリングへの影響による最も論争の1つです。
コア特性
- [単体インスタンス保証:]]]] 民間コンストラクタは外部インスタンスを防止します。静的メソッド(多くの場合)))は、唯一のインスタンスを返します。
- []グローバルアクセス:]]]] インスタンスは、多くの場合、公共の静的変数またはメソッドを介して、アプリケーション内の任意の場所からアクセス可能です。
- []レイジーまたはエイジャーの初期化:[[] インスタンスは、クラス読み込み時間(エイジャー)で作成するか、最初のリクエスト(レイジー)まで延期することができます。
シングルトンが適切であるとき
- []:[ 構成マネージャ、スレッドプール、接続プール、ロギングサービス、およびハードウェアインターフェイスドライバは、多くの場合、正確に1つのコントローラーが必要です。
- []:[] GUIフレームワークのキャッシュマネージャ、ファイルシステム抽象レイヤー、またはウィンドウマネージャ。
- [] リソース集中オブジェクト:[ 単一のインスタンスからシステム利益を生成し、再使用するために高価なオブジェクト。
導入検討
スレッド安全は最も一般的な下落です。 をチェックし、インスタンスを生成し、マルチスレッド環境で複数のインスタンスを生成できます。 ソリューションには、 でダブルチェックされたロック、静的内部クラス(Bill Pugh singleton)、またはJava の enum ベースのシングルトンが含まれます。 Python では、 を使用してスレッドセーフな初期化が標準的です。 eager と lazy の初期化の選択肢は、単一の作成に限っていれば、または Java でエンラムベースのシングルトンが保証されます。
批判的および落札
シングルトンは、多くの場合、アンチパターンと見なされます。なぜなら、グローバル状態を導入しているため、ユニットテストが困難になるからです。テストは順に依存せず、分離しにくい状態になります。また、依存関係を隠します。を呼ぶクラスは、シングルトンのコンクリートクラスにしっかりと結合されます。 現代の慣行は、依存症注射を使用して、シングルトンを共通のインスタンスとして供給し、テストでモックを置換できるようにします。 さらに、分散システム(egless)のシングルトンは、ネットワーク全体で1つのスコープが必要です。
工場方法 細部のパターン
Factory Method パターンはオブジェクトを作成するためのインターフェイスを定義しますが、サブクラスはどのクラスをインスタンス化するかを決定します。クライアントからオブジェクトの作成の責任をクライアントからファクトリーメソッドにシフトし、オープン/クローズドの原則を促進します。
コア特性
- [] 生成ロジックをカプセル化:[ クライアントコードは、具体的なクラスを知らない。抽象的な製品タイプで動作します。
- []拡張性:[]]]] 既存のクライアントコードを変更することなく、新しいコンクリート工場を作成することで、新しい製品タイプを追加できます。
- [] 定義されたインスタンス化:[]]] は、入力、設定、またはコンテキストに基づいて、実行時にインスタンス化するクラスが決定されます。
工場工法が適切である場合
- []関連オブジェクトの家族:[]:システムが一般的なインタフェースを共有する複数の製品バリエーションで動作する必要がある場合、例えば、異なるデータベースドライバ、ドキュメントエクスポート形式、またはUIテーマ。
- []コンクリート実装からクライアントコードをデカップリング:[]] クライアントは工場メソッドを呼び出し、抽象的なインターフェイスに従ったオブジェクトを受け取ります。 コンクリートクラスへの変更はクライアントに影響を与えません。
- [ 構成主導の生成:[] 設定ファイル、環境変数、またはランタイム条件に基づいて、コンクリート工場が使用する起動時にアプリケーションを決定できます。
導入検討
典型的なFactoryメソッドは、工場メソッド(多くの場合抽象化)を宣言する抽象的な[クラスを使用します。具体的な作成者は、特定の製品をインスタンス化するためにこのメソッドをオーバーライドします。継承なしの言語(例えば、JavaScript)では、工場は関数やクロージャをすることができます。このパターンは、実装を代替できる依存の注射容器でうまく動作します。一般的なバリアントは、静的ファクトリーメソッド(例:[FLT:])、(例:[FLT])、(例:[FLT])、(例:[F])、(例:[F])、(例:[F])、(例:[F])、(例:[F])、([F])、(例:[F])、(例:[F])、([F)、([F)、([F)、([F])、([F)、([F)、([F([F)、([F)[F([F)、([F)])])])])、([
実世界例: ドキュメントコンバーター
フォーマット間で文書を変換するアプリケーションを検討してください。 抽象[インターフェイスはメソッドを定義します。 工場メソッドは、入力拡張に基づいて[、[、または[[]]を返します。 新しいフォーマットを追加する(例、Markdown)は、新しいコンバータクラスのみを必要とし、工場のメソッドを更新します。変換パイプラインへの変更はありません。
直接比較:単トン対工場法
両方が創造パターンですが、その目標と取引オフはほぼ正当です。
| Aspect | Singleton | Factory Method |
|---|---|---|
| Primary goal | Ensure a single instance | Encapsulate object creation |
| Instance count | Exactly one | Many instances, but created through a factory |
| Control over class selection | Not relevant (always same class) | Subclasses or runtime logic choose the concrete class |
| Impact on maintainability | Can increase coupling (global access) | Reduces coupling (client depends on abstraction) |
| Testability | Often problematic (global state) | Good, as factories can be mocked |
| Extensibility | Limited (hard to subclass a singleton) | High (new products via new factories) |
問題が解決する際のシングルトンを選択することは、例えば、インスタンスのユニークさとグローバル・コオアディネーションです。例えば、書き込みを単一のファイルにシリアライズしなければならないロギングサービス。クライアントコードからオブジェクトの作成をデカップリングし、システムが新しい製品バリエーションで成長できるようにする際の、ファクトリーメソッドを選択します。例えば、異なるオペレーティングシステムでネイティブボタンをレンダリングする必要があるGUIツールキットです。
重なり(そしてNeitherを使うとき)
工場(例:単トン)として使用される単トンがさまざまなオブジェクトを作成する方法を知っているのを見ることは一般的です。このアプローチは、両方のパターンを組み合わせますが、グローバルな状態の欠点を継承します。より良い選択肢は、工場の依存性を注入し、工場自体を平凡なクラスとして維持することです。単板は工場にとって間違った選択肢です。目標がアプリケーション全体で工場インスタンスを共有する場合、依存の注入コンテナは、その実例を単板に使わずに、工場自体を単板に注入することができます。
現代のアプリケーションのための実用的な検討
試験および依存性注入
どちらのパターンも異なる方法でテストと相互作用します。 単調はユニットテストに置き換えることは珍しく困難です。 共通の回避策は、単調のためのインターフェイスを導入し、テストダブルを提供することですが、パターンのシンプルさを損なうことです。 工場方法、一方、テストでモック工場を提供することで簡単に交換されます。 現代のフレームワーク(春、ユニティ、グイス)では、コンテナは単調スクーピングを自動的に処理し、手動でパターンを実装する必要があります。
並列化と分散型システム
シングルトンは、複数のプロセスやノードをスパンさせることができないため、分散システムで分解します。 共有リソースでは、共有データベース、Redisなどのキャッシュ、またはシングルトンパターンではなく、リーダーの選挙を使用します。 ファクトリーメソッドは、分散コンテキストでも適用されます。 単に各サービス境界内でオブジェクトを作成します。
リアルワールドソリューションのパターンを組み合わせる
多くのプロダクションシステムは、これらのパターンをインテリジェントに組み合わせます。例えば、[]単トン接続プールは、ファクトリーメソッドを使用して、さまざまな種類の接続(例えば、読み取り専用対読み取り書き込み)を作成する場合があります。単行は、アプリケーションごとに1つのプールを1つ確保します。一方、ファクトリーメソッドは接続オブジェクトの作成を処理することになります。別の例:単行 ドキュメントジェネレータは、工場の形式をレンダリングする方法をレンダリングするためのメソッドを生成します。
避けるべき一般的な間違い
- ]工場が接種するときに単調で使用:[]]) 性能上の理由でクラスを1つのインスタンスだけしたい場合、シングルトンスコープの依存注射は、グローバルアクセサよりもクリーナーです。
- []オブジェクト作成時にファクトリーメソッドをトバイアルで固定します:[]])オブジェクトタイプが変化し、サブクラスがない場合、単純なコンストラクタはより明確です。
- []工場と製品ファミリー間のタイのカップリング:[ 他所に所属する工場方法の構成やビジネスロジックを置くことを避けてください。
- シングルトンのスレッド安全を強制的に:[]] サーバ環境では、非スレッドセーフなシングルトンは、負荷下で腐敗状態を生成できます。
コンテンツ
単調で工場工法は、ソフトウェア設計における基本的異なる役割を果たす。単調は、グローバルな協調のための単一のインスタンスを強制する。ファクトリーメソッドは、ランタイムの分散性と拡張性をサポートするオブジェクト作成を抽象化する。それらの間で選択すると、あなたの主な懸念がインスタンスのユニークさや柔軟性であるかを評価する必要があります。Neitherパターンはシルバー弾丸であり、テスト可能性、カップリング、複雑さのトレードオフを導入しています。自分の強みと限界を理解することによって、エンジニアは、しばしば、それらを組み合わせるように、それらを適用することができます。
更に読むには、]の古典的なGoFパターンを参照してください。Refactoring.Guruと]]Factory Method]。 また、Martin Fowlerの]Registryを単トンの代替として、 Factory Method Pattern:言語の言語実装のための言語の]]の解析を検討してください。