インスタンスを1つだけ持つクラスを作成するのは悪い考えですか?


9

一度だけインスタンス化されるクラスを作成するのは悪いコーディングの実践/設計ですか?

私はいくつかの変数と関数をクラスの下でグループ化して「見栄え」を良くするために(より良い説明がないため)いくつかの変数と関数を持っていますが、それらは単にグローバル変数とグローバル関数にすることができます。

(ところで、私はJavaScript、AngularJS、Express、MongoDBを使用しています。)


2
おそらく、シングルトンクラスが必要です。ただし、クラスにバインドすることは適切ではありません。
NeonGlow 2013年

2
シングルトンパターンは不良です。単一のインスタンスが正しい解決策になる場合があります。
ブライアンチェン

4
「シングルトン」も「シングルインスタンス」も、「ある程度関連している」グローバルなものをグループ化するための優れたソリューションではありません。そのような説明を聞くとき、私は常にこれを警告信号として捉えます。しかし、真剣に答えるには、グループ化する変数と関数の例を(実際の名前と意味とともに)教えてください。
Doc Brown、

2
シングルトンパターンは必ずしも悪いことではありません。それは使い過ぎる傾向があるというだけです。
Stephen

JavaScriptでシングルトンを適用することは技術的にも可能ですか?
エイミーブランケンシップ2013年

回答:


10

オブジェクトがイーサネット接続やオペレーティングシステムのタスクマネージャーなどの単一のリソースを表す場合、クラスの単一のインスタンスは意味があります。

関数は、そのクラスのインスタンスの変数に作用する場合にのみクラスに入れられます。そうでない場合、メンテナはそのクラスの意図について混乱します。

通常、アプリにグローバル変数があるのには十分な理由があります。それらの共通の目的を見つけて、この目的を中心にクラスを設計してください。それはデザインを明確にするだけでなく、あなたの心も明らかにします。


2
+1、しかし私は付け加えたいと思います:「それらの変数グローバルであるという唯一の共通の目的であるならば、それらを異なるクラスに置いたほうがよいです。」
Doc Brown、

13

インスタンス化が1回だけ終了するクラスを作成しても問題はありません。

いくつかの変数と関数をクラス内にまとめることが理にかなっている場合、意味論的な価値がある場合、またはコードの読み取りと操作が簡単な場合は、メンテナに感謝します。

ただし、非常に間違っている可能性があるのは、内部から一意性を強制することです。

多くの人は、何かのインスタンスが1つだけ必要になると思ったらすぐにシングルトンパターンを起動する傾向があります。たとえば、コンテキストを詳細に説明していない方法を参照してください。それでも、ほとんどの回答はシングルトンを使用することをすでに提案しています。そして、何らかの理由である時点で別のインスタンスが必要になった場合、クラスは多くのコードを変更せずにインスタンスを実行できないため、設計が失敗する可能性があります。

結論として、1つのインスタンスで問題ありませんが、次のことを確認してください。

  1. あなたは一つだけ必要なインスタンス、または
  2. 複数のインスタンスを持つことはできません(私の経験では非常にまれなケースです)。

1
re:#2、これが有効であるとは思いません。オブジェクトがNuclearPowerStationCentralCommandControllerで、所有している原子力発電所が1つだけである場合でも、テスト用のMockNuclearPowerStationCentralCommandControllerがないことを真剣に言っているのではありませんか。
Phoshi 2013年

より深刻ですがそれほど明白ではない問題は、シングルトンの実装が少し異なる必要がある場合、ほとんどの言語では不可能です。シングルトンを取得する方法は、インスタンスを渡すのではなく、直接それにアクセスすることだからです。 。
エイミーブランケン

@Phoshi:何かが1つしか存在できない場合、コードは参照を保持しなくてもそれを使用できます。複数のインスタンスの存在が許可されている場合、コンシューマはそれらへの参照を保持する必要があります。これによりオブジェクトのストレージ要件が増えるだけでなく、コンシューマは他のコンシューマが同じオブジェクトへの参照を保持していると想定できなくなります。これにより、かなり複雑になります。複雑さが最終的に必要になる場合は、後で追加するよりも早く追加することをお勧めしますが、必要でない場合は、回避することをお勧めします。
スーパーキャット2014年

@supercat:1つの参照に相当するメモリ使用量を追加することは、圧倒的な大多数の場合にはまったく無関係であり、それがDIを回避するための十分な理由ではないと私は思います。だれもが同じインスタンスを持っているとはもう想定できません。それは問題ではありません。インターフェースのセマンティクスが保持されている限り、すべてのインスタンスが異なっていてもかまいません。とにかく、私が言ったように、インスタンスが1つだけになることは決してありません。テスト用に少なくとももう1つ必要ですが、要件が変更されないという想定にリスクを負いますか?
Phoshi

@Phoshi:メモリ使用量は問題ではありません。問題は、オブジェクトを異なる方法で追加できることです。たとえば、の2つのインスタンスのアイテムDictionary<TKey,KTValue>が区別されるとはどういう意味かを検討してください。インスタンスのすべてのインスタンスがDictionary<TKey,KTValue>同じを使用するIEqualityComparer場合、あいまいさはありませんが、それらが異なる同値関係を定義する異なるコンパレーターを使用できる場合、a.ContentsDistinctFrom(b)常に等しいように慎重に定義することが可能であることを知りませんb.ContentsDistinctFrom(a)
スーパーキャット2014年

3

一度だけインスタンス化されるクラスを作成するのは悪いコーディングの実践/設計ですか?

いいえ、インスタンス化が1回だけであっても、そのためのクラスが必要です。ただし、現在および将来、常に 1つのインスタンスのみが必要になると限りません。

ゲームを作成し、プレーヤークラスがあるとします。

class Player {
    ...
}

ゲームで1つのプレーヤークラスをインスタンス化し、常に同じオブジェクトを使用します。何も問題はありません。

ただし、シングルトンで作成しないでください。今日、あなたはあなたのゲームを設計し、「まあ、それは常に 1人用のゲームになるでしょう。私は私のプレーヤーにシングルトンを使用します」と考えています。しかし、バージョン2では、マルチプレイヤーを実装したい場合があります-そして、あなたはトラブルに巻き込まれています。デザインは複数のプレーヤーのインスタンス化をサポートしていないため、多くのコードを書き直して適応させる必要があります。

キャッシュについても同様です。またはロガー。またはネットワークインターフェース。今日、あなたは確かに必ず1つだけ必要だと思います。しかし、将来のバージョンでは、秒を追加する必要があります。この状況に注意してください。


1

シングルトンクラスがあり、これは一般的なデザインパターンです。

インスタンス化されないクラスもあります。永続的な状態で動作しない関数がある場合(たとえば、入力を受け取って変換する場合)、通常は静的メソッドを使用できます。一部の言語(Javaなど)では、これらの静的メソッドはクラスで宣言されますが、クラス自体はインスタンス化されません。


1

シングルトンパターンは一般的です。クラスの単一インスタンスを強制することができます。

しかし、一部では一般的すぎるため、アンチパターンになります。これは、グローバルな状態と実質的に同じだからです。また、グローバルな状態は、モックやテストが困難であり、デバッグも困難です。ただし、同時に、コード内のすべての場所でこの1つのインスタンスを明示的に渡す必要があるため、コードが大きく膨らむ可能性があります。しかし、これは適切なアーキテクチャについて考えるようになります。多数のクラスがこの1つのシングルトンを使用している場合、それらが何らかの形で関連していて、それらの共通の祖先を作成すると、この1つのインスタンスがカプセル化されます。


1

何かが普遍的に悪いと仮定するのは悪いことです。あなたの場合、それは良いアイデアかもしれませんが、コアでOOではない言語を使用していることを考えると、ルーズなメソッドと変数を使用して、それらを他の仕事。


1

1つで2つの質問をしています。

  1. いいえ、インスタンスが1つしかないクラスがあっても問題はありません。
  2. 変数とメソッドをクラスにグループ化することは、それを正当な理由なく行うことは悪い設計です。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.