web-dev-qa-db-ja.com

シングルトンに代わるものは、1つのインスタンスしか持てないクラスにありますか?

ゲームのハードウェアのさまざまな部分を抽象化して表現する必要があります。ゲームのロジックを管理するようなことを行うコードを、API /プラットフォーム固有のコードまたは醜い実装の詳細であるコードから分離しようとしています。

このような:

std::unique_ptr<IDevice> device(CreateDevice());

IGraphicsDevice *graphics = device->getGraphicsDevice();
ISoundDevice *sound = device->getSoundDevice();
IWindow *window = device->getWindow();
IJobManager *jobmanager = device->getJobManager();
//etc

私が見た1つの解決策は、これらすべてを単にグローバルとして配置してmainで初期化することでしたが、できればそれを避けたいのです。より良いWordがないため、それらが「醜い」ものであることがわかります。また、自分でグローバルに初期化されるライブラリの初期化が必要なため、複数のインスタンスを許可することもできません。

これにはシングルトンパターンに代わるものはありますか?

複数のインスタンスがエラーにつながる可能性が高いことは知っていますが、これは設計上の悪い決定ですか?何か違うことはできますか?

5
user112513312

これはシングルトンパターンと呼ばれ、依存関係を隠し、コードの保守性を低下させるため、今日多くの人々によってアンチパターンと見なされています。

シングルトンパターンを使用する必要性は、他の悪い設計上の決定から生じる可能性がありますが、私はあなたのアーキテクチャと設計について何も知らないので判断できません。

とにかく、このパターンを取り除く方法の例を挙げましょう。ゲームでは、他のすべてを呼び出すある種のメインループが存在する可能性があります。簡単にするために、このメインループがオブジェクトに含まれていると仮定しますが、これは必須ではありません。ループを含むオブジェクトを作成するときは、サンプルコードで作成したオブジェクト(またはそれらへの参照)をそのオブジェクトに渡します。最も一般的な例を示すために、適切なコンストラクターまたはセッターメソッドを介してそれらを渡すことが可能です。 方法メインループでこれを行うには、クラスの設計に大きく依存しますが、次のようなレンダリングを実行できます。

while(running)
{
    game_state->update();
    renderer->render_state(game_state);
}

このアプローチの利点は、グローバルオブジェクトまたはシングルトンの必要性を排除し、オブジェクトがデバイスオブジェクトの作成方法を認識しないようにすることです。オブジェクトが知っておくべき唯一のことは、使用できるいくつかのデバイス抽象化があることです。彼らは他に何も知る必要はありません。

このアプローチは依存性注入と呼ばれ、最新のOO設計の非常に重要なパターンであると考えられています。

12
Paul Kertscher