3.1 シングルトン
シングルトンは、シングルスレッド アプリケーションが何らかのクラスの単一インスタンスを持つことを保証し、このインスタンスへのグローバル アクセス ポイントを提供する汎用設計パターンです。
初心者プログラマは、ユーティリティ メソッドを静的クラス (静的メソッドのみを含むクラス) にアセンブルすることを好むことがよくあります。このアプローチには、多くの欠点があります。たとえば、そのようなクラスのオブジェクトへの参照を渡すことができない、そのようなメソッドのテストが難しいなどです。
代替案として、シングルトン クラスのソリューション、つまりオブジェクトを 1 つだけ持つことができるクラスが提案されました。このオブジェクトを作成しようとすると、オブジェクトがまだ存在しない場合にのみ作成されます。それ以外の場合は、既存のインスタンスへの参照が返されます。
多くの場合、より広範な機能が利用可能になるため、クラスのインスタンスを使用できることが重要です。たとえば、このクラスはいくつかのインターフェイスを実装でき、そのオブジェクトをインターフェイスの実装として他のメソッドに渡すことができます。一連の静的メソッドでは実行できないこと。
長所:
- メソッドは静的クラスではなくオブジェクトにバインドされます。オブジェクトは参照によって渡すことができます。
- オブジェクト メソッドは、テストとモックがはるかに簡単です。
- オブジェクトは必要な場合にのみ作成されます (遅延オブジェクト初期化)。
- 起動に必要のないシングルが多数ある場合は、プログラムの初期起動を加速します。
- さらに、単独でテンプレート戦略または複数のそのようなオブジェクトに変えることができます。
マイナス点:
- スレッド間の競合と遅延を制御することがより困難になります。
- マルチスレッドの「孤独な」ものを「頭から」書くのは困難です。理想的には、長年存在するシングルトンへのアクセスでは、ミューテックスを開いてはなりません。より優れた実証済みのソリューション。
- 未完了の 1 つのスレッドをめぐって 2 つのスレッド間で競合が発生すると、遅延が発生します。
- オブジェクトが長時間にわたって作成されている場合、遅延によってユーザーの操作が妨げられたり、リアルタイムが中断されたりする可能性があります。この場合、その作成をプログラムの初期化の段階に移すことをお勧めします。
- 単体テストには特別な機能が必要です。たとえば、ライブラリを「非孤独」モードにして、テストを相互に完全に分離するなどです。
- 起動可能性は構成に依存するため、「最も単純な起動可能性」という概念さえ消えてしまうため、完成したプログラムをテストするための特別な戦術が必要になります。
3.2 工場 [方法]
ファクトリ メソッドは、特定のクラスのインスタンスを作成するためのインターフェイスをサブクラス (クラス継承者) に提供する汎用設計パターンです。作成時に、子孫はどのクラスを作成するかを決定できます。
つまり、このテンプレートはオブジェクトの作成を親クラスの子孫に委任します。これにより、プログラム コード内で具象クラスを使用せずに、より高いレベルで抽象オブジェクトを操作できるようになります。
このパターンは、オブジェクトを作成するためのインターフェイスを定義しますが、オブジェクトのベースとなるクラスの決定はサブクラスに任せます。ファクトリ メソッドを使用すると、クラスがサブクラスの作成を委任できるようになります。次の場合に使用されます。
- クラスは、どのサブクラスのどのオブジェクトを作成する必要があるかを事前に知りません。
- クラスは、作成するオブジェクトがサブクラスによって指定されるように設計されています。
- クラスはその責任をいくつかのヘルパー サブクラスの 1 つに委任し、どのクラスがこれらの責任を引き継ぐかを決定することが計画されています。
3.3 抽象ファクトリー
抽象ファクトリは、具体的なクラスを指定せずに、関連するオブジェクトまたは相互依存するオブジェクトのファミリーを作成するためのインターフェイスを提供する汎用デザイン パターンです。
パターンは、システム コンポーネントを作成するためのインターフェイスである抽象クラス Factory を作成することによって実装されます (たとえば、ウィンドウ インターフェイスの場合、ウィンドウとボタンを作成できます)。次に、このインターフェイスを実装するクラスが作成されます。
これは、プログラムが作成される新しいオブジェクトのプロセスやタイプから独立している必要がある場合に使用されます。関連するオブジェクトのファミリーまたはグループを作成する必要がある場合、同じコンテキスト内でこれらの異なるセットのオブジェクトを同時に使用する可能性を排除します。
強み:
- 特定のクラスを分離します。
- 製品ファミリーの置き換えを簡素化します。
- 製品の互換性を保証します。
プログラムがファイル システムで動作するとします。Linux で作業するには、LinuxFile、LinuxDirectory、LinuxFileSystem オブジェクトが必要です。また、Windwos で作業するには、WindowsFile、WindowsDirectory、WindowsFileSystem クラスが必要です。
Path.of() によって作成される Path クラスがまさにそのようなケースです。Path は実際にはクラスではなくインターフェイスであり、WindowsPath と LinuxPath の実装があります。また、どのような種類のオブジェクトが作成されるかはコードからは隠されており、実行時に決定されます。
3.4 プロトタイプ
プロトタイプはジェネレーティブ デザイン パターンです。
このパターンは、プロトタイプ インスタンスを使用して作成されるオブジェクトの種類を定義し、このプロトタイプをコピーすることで新しいオブジェクトを作成します。これにより、実装から離れて、「インターフェイスを介したプログラミング」の原則に従うことができます。
階層の最上位にあるインターフェイス/抽象クラスは戻り型として指定され、子孫クラスはそこでこの型を実装する継承クラスを置き換えることができます。簡単に言えば、これは、コンストラクターを使用してオブジェクトを作成するのではなく、別のオブジェクトのクローンを作成することによってオブジェクトを作成するパターンです。
パターンは次の目的で使用されます。
- アプリケーションにとって法外なコストがかかる場合に、標準的な方法 (つまり、コンストラクターを使用すること) でオブジェクトを作成するという追加の作業を回避できます。この場合、オブジェクトの祖先階層全体のコンストラクターも呼び出されることになります。
- 抽象ファクトリ パターンのように、クライアント アプリケーションでオブジェクト クリエーターを継承することは避けてください。
プログラムが製品の作成、構成、表示方法を気にしない場合は、このデザイン パターンを使用します。
- インスタンス化されたクラスは、たとえば動的ロードを使用して実行時に決定されます。
- 製品クラス階層と並行するクラス階層またはファクトリ階層の構築を避けたい場合。
- クラス インスタンスは、いくつかの異なる状態のいずれかになります。毎回手動で適切な状態のクラスをインスタンス化するよりも、適切な数のプロトタイプを設定してクローンを作成する方が便利な場合があります。
GO TO FULL VERSION