シングルトンの何が悪いのですか?[閉まっている]


1983

シングルトンパターンはの完全払込メンバーであるのGoFパターンの本が、それは最近、むしろ開発者の世界で孤立したようです。私はまだ特に多くのシングルトンを使用しています。特にファクトリークラスでは、マルチスレッドの問題(実際には他のクラスと同様)に少し注意する必要がありますが、なぜそれほどひどいのかはわかりません。

スタックオーバーフローは特に、シングルトンが悪であることに誰もが同意していると想定しているようです。どうして?

事実、参考文献、または特定の専門知識」で回答をサポートしてください


6
シングルトン設計を使用することで、コードを適応させようとしたため、最近、やけどを負ったと言わざるを得ません。私は自由な時間にそれをしているので、これをリファクタリングするのはほとんど面倒です。生産性の悪いニュース。
Marcin

71
答えには多くの「欠点」がありますが、パターンが良いときの良い例をいくつか見たいのですが、悪いところとは対照的です
DGM

50
私は数か月前にこの件に関するブログ投稿を書きました:jalf.dk/blog/2010/03/…-そして私はそれをはっきり言ってみましょう。シングルトンが適切なソリューションである単一の状況を個人的に考えることはできません。それはそのような状況が存在しないという意味ではありませんが、...それらをまれと呼ぶのは控えめな表現です。
2010年

8
@AdamSmithそれはあなたする必要があるという意味ではありませんが、それはあなたそのようにそれにアクセスできることを意味します。そのようにアクセスするつもりがない場合は、そもそもシングルトンにする必要はほとんどありません。つまり、「シングルトンとして扱わなければ、シングルトンを作成しても害はありません。ええ、素晴らしいです。車を運転しなければ、車は汚染されません。しかし、そもそも車を購入しない;)(完全な開示:私は実際には車を持っていない)
jalf

35
この全体のトピックの最悪の部分は、シングルトンを嫌う人々が、代わりに何を使うべきかについて具体的な提案をすることはめったにないということです。たとえば、このSO記事全体のジャーナル記事や自費公開ブログへのリンクは、シングルトンを使用しない理由(そして、それらはすべて優れた理由です)を何度も繰り返しますが、置換に関して非常にスリムです。でも、たくさん手を振っています。シングルトンを使用しない理由を新しいプログラマーに教えようとする私たちには、指摘すべき優れたサードパーティの反例があまりなく、考案された例しかありません。それは疲れています。
Ti Strga

回答:


1294

ブライアンバトンから言い換え:

  1. それらは一般的にグローバルインスタンスとして使用されますが、なぜそんなに悪いのですか?インターフェースを介してアプリケーションを公開するのではなく、コードでアプリケーションの依存関係を非表示にするためです。何かをグローバルに渡さないようにすることはコードの匂いです。

  2. 彼らは単一の責任の原則に違反します。彼らは彼ら自身の創造とライフサイクルを制御するという事実のおかげで。

  3. これらは本質的にコードを密結合します。これにより、多くの場合、テスト中のそれらを偽装することがかなり困難になります。

  4. それらはアプリケーションの存続期間中状態を持ち歩きます。テストを注文する必要がある状況に陥る可能性があるため、テストへのもう1つのヒットは単体テストにとっては大きな問題です。どうして?各ユニットテストは互いに独立している必要があるためです。


324
私はあなたに同意しません。コメントは600文字しか許可されていないため、これについてコメントするブログ投稿を作成しました。以下のリンクを参照してください。 jorudolph.wordpress.com/2009/11/22/singleton-considerations
ヨハネスルドルフ

61
ポイント1と4では、シングルトンは有用であり、実際には(特にDBからの)データのキャッシュにはほぼ完璧です。パフォーマンスの向上は、単体テストのモデリングに伴う複雑さをはるかに超えています。
大福

56
@Dai Bok:「データをキャッシュする(特にDBから)」これを行うには、プロキシパターンを使用します...
paxos1977

55
うわー、素晴らしい反応。ここでは過度に攻撃的な表現を使用している可能性があるため、否定的なギアの質問に答えていたことを覚えておいてください。私の答えは、シングルトンの不適切な使用から発生する「アンチパターン」の短いリストでした。完全な開示; 私も時々シングルトンを使用しています。SOについてより中立的な質問があり、シングルトンを良いアイデアと見なすことができる優れたフォーラムになります。たとえば、stackoverflow.com / questions / 228164 /…
Jim Burger

21
これらは、マルチスレッド環境でのキャッシングにはあまり適していません。限られたリソースをめぐって戦う複数のスレッドでキャッシュを簡単に無効にすることができます。[シングルトンで維持]
修道士

449

シングルトンは1つ(そして1つだけ)の問題を解決します。

リソースの競合。

あなたはそれがあるリソースを持っているなら

1)は単一のインスタンスのみを持つことができます。

2)その単一のインスタンスを管理する必要がある

シングルトンが必要です。

多くの例はありません。ログファイルは大きなものです。単一のログファイルを単に破棄する必要はありません。フラッシュし、同期して、適切に閉じたい。これは、管理する必要がある単一の共有リソースの例です。

シングルトンが必要になることはまれです。彼らが悪い理由は、彼らがグローバルのように感じ、GoF Design Patternsの本の完全に支払い済みのメンバーだからです。

グローバルが必要だと思うとき、恐らくひどい設計ミスを犯しています。


43
ハードウェアも一例ですよね?組み込みシステムには、シングルトンを使用する可能性のあるハードウェアがたくさんあります。<grin>
ジェフ

170
完全に同意する。練習がその場所にあるかもしれないという認識なしで、「この練習は悪い」という断固たる話し合いがたくさんあります。しばしば誤用されるので、慣習は単に「悪い」だけです。シングルトンパターンは、適切に適用されている限り、本質的に問題はありません。
Damovisa 2009

53
実際の原則によるシングルトンは非常にまれです(そして、プリンターキューは確かに1つではなく、どちらもログファイルではありません-log4jを参照してください)。多くの場合、ハードウェアは原則ではなく偶然の一致によるシングルトンです。PCに接続されているすべてのハードウェアは、せいぜい偶然のシングルトンです(複数のモニター、マウス、プリンター、サウンドカードを考えてみてください)。500 mio $の粒子検出器でさえ、偶然と予算の制約によるシングルトンです-ソフトウェアには適用されないため、シングルトンはありません。電気通信では、電話番号も物理的な電話もシングルトンではありません(ISDN、コールセンターなど)。
digitalarbeiter 2010

23
ハードウェアはさまざまなリソースのインスタンスを1つだけ持つことができますが、ハードウェアはソフトウェアではありません。開発ボード上の単一のシリアルポートをシングルトンとしてモデル化する必要がある理由はありません。実際、それをモデル化すると、2つのポートを持つ新しいボードへの移植が難しくなるだけです。
dash-tom-bang

19
つまり、2つの同一のクラスを記述し、多くのコードを複製して、2つのポートを表す2つのシングルトンを持つことができるようにしますか?2つのグローバルSerialPortオブジェクトを使用するのはどうですか?ハードウェアをクラスとしてモデル化しないのはどうですか?また、なぜグローバルアクセスを意味するシングルトンを使用するのでしょうか。あなたがしたいですか、すべてのあなたのコード内の関数は、シリアルポートにアクセスできるようにするには?
10

352

一部のコーディングスノッブは、それらを美化されたグローバルとして見下しています。多くの人がgotoステートメントを嫌うのと同じように、グローバルを使用するという考えを嫌う人もいます。何人かの開発者がグローバルを回避するために途方もない時間を費やして、失敗の容認として1つを使用することを検討したのを見ました。奇妙だが真実。

実際には、シングルトンパターンは、概念のツールキットの有用な部分であるプログラミング手法にすぎません。時々、あなたはそれが理想的な解決策であると思うかもしれないので、それを使ってください。しかし、デザインパターンの使用について自慢できるようにそれを使用することは、それが単にグローバルであるため、使用を拒否するのと同じくらい愚かです。


17
シングルトンで私が目にする失敗は、人々が何らかの形で「より良い」ので、グローバルの代わりにそれらを使用することです。問題は(私が見ると)、これらの場合にシングルトンがテーブルにもたらすものとは無関係であるということです。(たとえば、実際にコンストラクターを使用していない場合でも、最初に使用するコンストラクターをシングルトン以外で実装するのは簡単です。)
dash-tom-bang

21
「私たち」がそれらを見下ろす理由は、「私たち」がそれらが間違って使用されていることを非常に頻繁に、そしてあまりにも頻繁に見ているためです。「私たち」は、彼らが彼らの原因の場所を持っていることを知っています。
Bjarke Freund-Hansen、2012

5
@フィル、あなたは「時々それが理想的な解決策であると思うかもしれないのでそれを使う」と述べました。わかりました、それで正確にどの場合にシングルトンが役に立つと思いますか?
Pacerier 2014年

22
@Pacerier、以下の条件がすべて満たされる場合:(1)いずれか1つだけが必要、(2)多数のメソッド呼び出しで引数としてその1つを渡す必要がある、(3)受け入れることを希望するどこかで気の利いたものを渡さないことで、コードのサイズと複雑さを即座に削減する代わりに、いつかリファクタリングしなければならない可能性があります。
アンチノーム2014

18
私はこれが何にも答えているとは思わず、単に「時々それが合うかもしれないし、そうでないかもしれない」とだけ言っています。OK、でも、なぜ、いつ?何がこの答えをモデレートへ議論以上にするのですか?
ギルデンスタン2014年

219

GoogleのMisko Heveryが、まさにこのトピックについていくつかの興味深い記事を持っています...

シングルトンは病理学的である嘘つきは、依存関係の連鎖を理解し、アプリケーションを開始またはテストすることをシングルトンがどのように困難にすることができるかを示すユニットテストの例を持っています。これは虐待のかなり極端な例ですが、彼の主張は今でも有効です。

シングルトンは、グローバルステートにすぎません。グローバル状態はそれを作り、オブジェクトがAPIで宣言されていないものを密かに取得できるようにします。その結果、シングルトンはAPIを病的嘘つきにします。

すべてのシングルトンがどこにあるかというと、依存性注入によってインスタンスを必要とするコンストラクターにインスタンスを簡単に取得できるため、最初の記事で否定されたグローバルなシングルトンの背後にある根本的なニーズが緩和されます。


8
この件に関するMiskoの記事は、現時点で最も優れているものです。
Chris Mayer

22
最初のリンクは実際にはシングルトンの問題に対処するのではなく、クラス内の静的依存関係を想定しています。パラメータを渡すことで特定の例を修正し、それでもシングルトンを使用することは可能です。
DGM

17
@DGM:まさに-実際には、記事の「根拠」の部分と「シングルトンが原因」の部分との間には、大きな論理的な断絶があります。
Harper Shelby

1
MiskoのCreditCard記事は、このパターンの誤用の極端な例です。
アレックス

2
2番目の記事を読むシングルトンは、実際には説明されているオブジェクトモデルの一部です。ただし、グローバルにアクセスできる代わりに、これらはFactoryオブジェクトにプライベートです。
FruitBreak 2012年

121

混乱の原因は、シングルトンパターンの実際の適用を人々が知らないためだと思います。私はこれを十分に強調することはできません。シングルトンは、グローバルをラップするパターンではありません。シングルトンパターンは実行時に特定のクラスのインスタンスが1つだけ存在することを保証するためにのみ使用する必要があります

シングルトンはグローバルに使用しているので、シングルトンは悪だと人々は考えています。シングルトンが見下されているのは、この混乱のためです。シングルトンとグローバルを混同しないでください。それが意図された目的で使用された場合、シングルトンパターンから非常に大きなメリットが得られます。


20
アプリ全体で利用できるその1つのインスタンスは何ですか?ああ。 グローバル。「シングルトンはグローバルをラップするパターンではありません」は、定義によって、パターンがグローバルインスタンスの周りにクラスをラップするため、単純または誤解を招くものです。
cHao

26
もちろん、アプリケーションの起動時にクラスのインスタンスを1つ作成し、そのインスタンスを、インターフェースを介して、それを使用するものに挿入することができます。実装は、1つしか存在できないことを気にする必要はありません。
スコットウィットロック2014年

4
@Dainius:結局、実際にはありません。もちろん、インスタンスを任意に置き換えることはできません。(あなたがそうするそれらのfacepalmを誘発する瞬間を除い。私は実際にsetInstance方法を見たことがあります。)しかし、それはほとんど問題ではありません-シングルトンを「必要とする」というウィニーも、カプセル化に関するおかしなことや何が悪いのかを知りませんでした変更可能なグローバルな状態なので、彼は役に立ちましたか?シングル。フィールド。(そして、そうです、これは起こります。たくさんあります。野生で見たほとんどすべてのシングルトンは、設計により変更可能であり、しばしば
恥ずかしい

4
@Dainius:大体、すでに持っています。「継承よりも構成を優先する」は、かなり長い間行われてきました。ただし、継承明らかに最良のソリューションである場合は、もちろんそれを自由に使用できます。シングルトン、グローバル、スレッディングgotoなどでも同じことが言えます。それらは多くの場合機能する可能性がありますが、正直言って、「機能する」だけでは不十分です。従来の知識に逆戻りしたい場合は、アプローチの方法を示すことができます。ある優れた従来のソリューションに比べて。そして、私はシングルトンパターンのそのようなケースを見たことがありません。
cHao

3
私たちがお互いを越えて話をしないように、私はグローバルに利用可能なインスタンスについて話しているだけではありません。そのためのケースはたくさんあります。私が話しているのは(特に、「capital-S Singleton」と言うとき)、GoFのシングルトンパターンです。これは、その単一のグローバルインスタンスをクラス自体に埋め込み、getInstanceまたは同様の名前のメソッドを介してそれを公開し、 2番目のインスタンス。率直に言って、その時点では、インスタンスが1つもない場合もあります。
cHao

72

シングルトンの悪い点の1つは、簡単に拡張できないことです。基本的に、動作を変更したい場合は、何らかのデコレータパターンなどを組み込む必要があります。また、ある1つのことを複数の方法で実行したい場合、コードのレイアウト方法によっては、変更がかなり面倒になる場合があります。

注意すべきことの1つは、シングルトンを使用する場合は、直接アクセスするのではなく、必要な人に渡してみることです。そうでない場合、シングルトンが行うことを実行する方法が複数ある場合は、シングルトンに直接アクセスする場合、各クラスが依存関係を埋め込むため、変更はかなり困難です。

だから基本的に:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

のではなく:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

この種のパターンは依存性注入と呼ばれ、一般的には良いことだと考えられています。

与えられた状況での使用が不適切であるかどうかのいずれかのパターンと同じように...それについて考えてみようと考える...ルールは、通常は破られるために作られ、そしてパターンが考えずにウィリーnilly適用すべきではありません。


17
えっと、どこでもこれを行うと、どこでもシンゲルトンへの参照を渡さなければならないので、シングルトンはもうありません。:)(これは通常、良いIMOです。)
Bjarke Freund-Hansen、2012

2
@ BjarkeFreund-Hansen-ナンセンス、あなたは何を話しているのですか?シングルトンは、一度インスタンス化されるクラスのインスタンスです。そのようなシングルトンを参照しても、実際のオブジェクトはコピーされず、参照されるだけです。同じオブジェクトがまだあります(読み取り:シングルトン)。
M. Mimpen 2013

2
@ M.Mimpen:いいえ、大文字のSシングルトン(ここで説明しているもの)はクラスのインスタンスであり、(a)1つのインスタンスのみが存在することを保証し、(b)クラスの独自のインスタンスを介してアクセスされます組み込みのグローバルアクセスポイント。何も呼び出す必要がないと宣言した場合getInstance()、(b)はまったく正しくありません。
cHao 2014

2
@cHao私はあなたをフォローしていないか、私が誰にコメントするか理解していません-これはBjarke Freund-Hansenへのものです。Bjarkeは、シングルトンの複数の参照があると、複数のシングルトンが存在することになると述べています。深いコピーがないので、それは確かに本当ではありません。
M.ミンペン、2014

6
@ M.Mimpen:私は彼のコメントを使って、セマンティック効果についてさらに言及します。への呼び出しを禁止するとgetInstance()、シングルトンパターンと通常の参照との1つの便利な違いを効果的に放棄できます。残りのコードに関する限り、単一性はもはやプロパティではありません。getInstance()存在するインスタンスの数を知っている、または気にする必要があるのは、これまでの呼び出し元だけです。呼び出し元が1つだけの場合、呼び出し元に参照を格納して再利用させるだけの場合よりも、クラスが単一性を確実に実施するための労力と柔軟性が高くなります。
cHao 14

69

シングルトンパターン自体は問題ではありません。問題は、オブジェクト指向の概念をしっかりと把握せずに、オブジェクト指向のツールを使用してソフトウェアを開発する人々がこのパターンをよく使用することです。このコンテキストでシングルトンが導入されると、シングルトンは、ほとんど使用しないヘルパーメソッドを含む管理できないクラスに成長する傾向があります。

シングルトンは、テストの観点からも問題です。それらは孤立した単体テストを書くのを難しくする傾向があります。制御の反転(IoC)と依存性注入は、単体テストに役立つオブジェクト指向の方法でこの問題を克服するためのパターンです。

ではガベージコレクト環境シングルトンはすぐにメモリ管理に関する問題になることができます。

シングルトンがボトルネックになる可能性があるマルチスレッドシナリオと同期の問題もあります。


4
私はそれが何年も前の糸であることを知っています。こんにちは@Kimoz uは言った:-シングルトンはすぐにメモリ管理に関して問題になる可能性があります。シングルトンとガベージコレクションに関してどのような問題が発生する可能性があるかについて、より詳細に説明したいと思います。
トーマス

@Kimoz、質問は「シングルトンパターン自体が問題ではないのはなぜですか?」そして、あなたは単にポイントを繰り返しましたが、シングルトンパターンの単一の有効なユースケースすら提供していません。
Pacerier 2014年

@Thomas。定義上、シングルトンは1つのインスタンスにのみ存在するためです。そのため、唯一の参照をnullに割り当てるのはしばしば複雑です。それは可能ですが、シングルトンがアプリで使用されなくなるポイントを完全に制御することを意味します。そして、これはまれであり、通常、シングルトン愛好家が求めているものとは正反対です。つまり、単一のインスタンスに常にアクセスできるようにする簡単な方法です。GuiceやDaggerなどの一部のDIフレームワークでは、シングルトンを削除することはできず、メモリに永久に残ります。(コンテナ提供のシングルトンは自家製のものよりはるかに優れていますが)。
Snicolas、2015年

54

シングルトンは静的メソッドを使用して実装されます。静的メソッドはモックやスタブができないため、単体テストを行う人は避けます。このサイトのほとんどの人々は、ユニットテストの大きな支持者です。それらを回避するために最も一般的に受け入れられている規則は、制御パターンの反転を使用することです。


9
これは、オブジェクト(ユニット)、関数(ユニット)、ライブラリ全体(ユニット)をテストできるユニットテストの問題のように聞こえますが、クラス(ユニット)の静的なもので失敗します。
v010dya 2014

2
とにかく、すべての外部参照をmocすると思いませんか?もしそうなら、mocシングルトンの問題は何ですか?そうでなければ、本当にユニットテストを行っていますか?
Dainius 2014年

@Dainius:インスタンスのモックは、クラスのモックよりもはるかに簡単です。アプリケーションの残りの部分からテスト中のクラスを抽出して、偽のクラスでテストすることが考えられますSingleton。ただし、これはテストプロセスを非常に複雑にします。1つには、今度はクラスを自由にアンロードできるようにする必要があります(ほとんどの言語では実際にはオプションではありません)。または、各テストで新しいVMを開始できる必要があります(読み取り:テストには何千倍も時間がかかる場合があります)。ただし、2つについては、依存関係Singletonは実装の詳細であり、テスト全体に漏れています。
cHao 2015年

Powermockは静的なものをモックできます。
Snicolas、2015年

オブジェクトのモックは、実際のオブジェクトを作成することを意味しますか?モックが実際のオブジェクトを作成しない場合、クラスがシングルトンであるか、メソッドが静的であるかが重要なのはなぜですか?
Arun Raaj

45

クラスタリングに関しても、シングルトンは良くありません。そのため、アプリケーションに「厳密に1つのシングルトン」はもうありません。

次の状況を考慮してください。開発者は、データベースにアクセスするWebアプリケーションを作成する必要があります。同時データベース呼び出しが互いに競合しないようにするには、thread-saveを作成しますSingletonDao

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

したがって、アプリケーションに存在するシングルトンは1つだけであり、すべてのデータベースはこの1つだけを通過しますSingletonDao。運用環境は次のようになります。 シングルシングルトン

これまでのところすべてが順調です。

ここで、クラスター内にWebアプリケーションの複数のインスタンスをセットアップすることを検討してください。さて、あなたは突然次のようなものを手に入れました:

多くのシングルトン

奇妙に聞こえますが、アプリケーションに多くのシングルトンがあります。そして、それはまさにシングルトンがそうであるべきではないものです:それの多くのオブジェクトを持つこと。これは、この例に示されているように、データベースへの同期呼び出しを行う場合に特に好ましくありません。

もちろん、これはシングルトンの悪い使い方の例です。しかし、この例のメッセージは次のとおりです。アプリケーションにシングルトンのインスタンスが1つしかないことは信頼できません。特に、クラスタリングに関してはそうです。


4
シングルトンの実装方法がわからない場合は、そのようにするべきではありません。自分が何をしているかわからない場合は、まずそれを見つけ、その後になって初めて必要なことを行う必要があります。
Dainius、2014年

3
これは興味深いです。質問があります。では、シングルトン(それぞれが異なるマシン/ JVMにある)が単一のデータベースに接続している場合、正確には何が問題なのでしょうか。シングルトンのスコープはその特定のJVMのみを対象としており、クラスターでも同じです。私たちの意図はアプリケーション全体で単一のオブジェクトだったので、この特定の状況が悪いと哲学的に言うだけでなく、この配置のために発生する可能性のある技術的な問題を見つけて喜んでいます。
Saurabh Patil 2016年

39
  1. グローバル変数として簡単に(ab)使用できます。
  2. シングルトンに依存するクラスは、単体で単体テストを行うのが比較的困難です。

33

独占は悪魔であり、非読み取り専用/可変状態のシングルトンは「本当の」問題です...

読んだ後シングルトンは、病理学嘘つきですで提案されているようにジェイソンの答え私は最良の提示例提供し、この小さなちらほら出くわしたシングルトンがしばしば誤用されているが。

グローバルは悪いです:

  • a。名前空間の競合が発生します
  • b。不当な方法で状態を公開します

シングルトンになると

  • a。それらを呼び出す明示的なオブジェクト指向の方法は、競合を防ぐため、aをポイントします。問題ではありません
  • b。状態のないシングルトンは(工場のように)問題ありません。状態を持つシングルトンは、再び2つのカテゴリに分類される可能性があります。それらは不変であるか、1回だけ書き込み、多くのファイルを読みます(config / propertyファイル)。これらは悪くないです。リファレンスホルダーの一種であるミュータブルシングルトンは、あなたが話しているものです。

最後の声明で彼はブログの「シングルトンは嘘つきだ」という概念について言及している。

これはモノポリーにどのように当てはまりますか?

独占のゲームを始めるには、まず:

  • 最初にルールを確立するので、全員が同じページにいます
  • ゲームの初めに皆が平等にスタートする
  • 混乱を避けるために、1組のルールのみが提示されています
  • ゲーム全体でルールを変更することはできません

さて、本当に独占をやったことがない人にとって、これらの基準は最高の状態で理想的です。独占の敗北は飲み込むのが難しいです。なぜなら、独占はお金の問題であり、もし負けた場合、他のプレイヤーがゲームを終えるのをじっくりと見なければならず、通常、損失は迅速でつぶれます。したがって、ルールは通常、他の人を犠牲にして一部のプレーヤーの自己利益を果たすために、ある時点でねじれます。

あなたは友達のボブ、ジョー、エドと独占をしています。あなたは帝国を急速に構築し、市場シェアを指数関数的に消費しています。対戦相手が弱くなり、血のにおいがし始めます(比喩的に)。あなたの相棒ボブは、彼のお金のすべてを可能な限り多くの低価値の物件にグリッドロックするために投入しましたが、彼は彼が期待したように高い投資収益率を受け取っていません。ボブは不運のストロークとしてボードウォークに着地し、ゲームから興奮します。

今やゲームはフレンドリーなサイコロの転がりから本格的なビジネスへと進んでいきます。ボブは失敗の例にされており、ジョーとエドは「あの男」のようになってしまいたくありません。それで、あなたが主役になることで、突然、あなたは敵になります。ジョーとエドは、テーブルの下での取引、バックザバックマネーインジェクション、過小評価されたハウススワッピング、そして一般的に、いずれかがトップに上がるまでプレイヤーとしての弱点となる練習を始めます。

次に、そのうちの1人が勝つ代わりに、プロセスが最初から始まります。突然、有限のルールのセットが動くターゲットになり、ゲームは、Survivor以降のすべての高評価の現実のテレビ番組の基礎を構成するタイプの社会的相互作用に退化します。なぜ、ルールが変化し、ルールがどのように/なぜ/何を表すのかについてコンセンサスがないためであり、さらに重要なのは、決定を下す人がいないためです。その時点で、ゲーム内のすべてのプレーヤーは自分のルールを作成し、2人のプレーヤーが疲れすぎてシャレードを維持し、ゆっくりと諦めるまで、混乱が続きます。

したがって、ゲームのルールブックがシングルトンを正確に表す場合、独占ルールブックは乱用の一例になります。

これはプログラミングにどのように適用されますか?

変更可能なシングルトンが存在する明らかなすべてのスレッド安全性と同期の問題は別として、1つのデータセットがある場合、複数の異なるソースによって同時に読み取り/操作でき、アプリケーション実行の存続期間中に存在します。たぶん、「ここで正しいタイプのデータ構造を使用していますか」と尋ねて、今がよい時でしょう。

個人的には、プログラマーがシングルトンをアプリケーション内のある種のねじれたクロススレッドデータベースストアとして使用することによってシングルトンを悪用するのを見てきました。コードに直接取り組んだので、それが遅く(スレッドセーフにするために必要なすべてのスレッドロックのため)、取り組むのが悪夢だった(同期バグの予測できない/断続的な性質のため)ことを証明できます。 「実稼働」条件下でテストすることはほとんど不可能です。確かに、システムはポーリング/シグナリングを使用してパフォーマンスの問題のいくつかを克服するように開発できたかもしれませんが、テストの問題を解決できず、「実際の」データベースがはるかに堅牢で同じ機能をすでに実現できるのに困る理由/スケーラブルな方法。

シングルトンは、シングルトンが提供するものを必要とする場合のみのオプションです。オブジェクトの書き込み専用の読み取り専用インスタンス。同じルールは、オブジェクトのプロパティ/メンバーにもカスケードする必要があります。


1
シングルトンがデータをキャッシュする場合はどうなりますか?
Yola、2014

@Yolaシングルトンが事前に決定された、または固定されたスケジュールで更新されるようにスケジュールされている場合、書き込み数が削減され、それによってスレッドの競合が減少します。それでも、同じ使用法をシミュレートする非シングルトンインスタンスをモックしない限り、シングルトンと対話するコードを正確にテストすることはできません。TDDの人々はおそらく適合しているでしょうが、それはうまくいくでしょう。
Evan Plaice、2014

@EvanPlaice:モックを使っても、と言うコードにいくつか問題がありますSingleton.getInstance()。リフレクションをサポートする言語は、One True Instanceが格納されるフィールドを設定することで、その問題を回避できる場合があります。ただし、IMOは、別のクラスのプライベートな状態をざっと見回すと、テストの信頼性が少し低下します。
cHao

28

シングルトンは単一インスタンスではありません!

他の回答とは異なり、私はシングルトンの何が問題になっているのかを話したくありませんが、適切に使用したときのパワフルで素晴らしいものを紹介します!

  • 問題:シングルトンはマルチスレッド環境での課題になる可能性があります
    解決策:シングルスレッドのブートストラッププロセスを使用して、シングルトンのすべての依存関係を初期化します。
  • 問題:シングルトンをモックするのは難しい。
    解決策:モックにメソッドファクトリパターンを 使用する

あなたはそれを継承MyModelするTestMyModelクラスにマップすることができます、どこにMyModel注入されるとあなたはTestMyModel混乱するでしょう。- 問題:シングルトンは破棄されないため、メモリリークを引き起こす可能性があります。
解決策:さて、それらを処分してください!アプリにコールバックを実装して、シングルトンを適切に破棄します。シングルトンにリンクされているデータをすべて削除し、最後にファクトリから削除します。

タイトルで述べたように、シングルトンは単一のインスタンスではありません。

  • シングルトンは読みやすさを向上させます。クラスを見て、どのシングルトンが注入されたかを確認して、依存関係を把握できます。
  • シングルトンはメンテナンスを改善します:シングルトンインジェクションを削除したクラスから依存関係を削除すると、依存関係を移動した他のクラスの大きなリンクに移動して編集する必要はありません(これは私にとっては臭いコードです@ジムバーガー)
  • シングルトンはメモリとパフォーマンスを改善します:アプリケーションで何かが発生し、コールバックの長いチェーンが提供されると、メモリとパフォーマンスを浪費し、シングルトンを使用することで仲介者を削減し、パフォーマンスとメモリ使用量を改善します(不必要なローカル変数の割り当てを回避することにより)。

2
これは、プロジェクト内の何千ものクラスのいずれかからグローバル状態へのアクセスを許可するというシングルトンに関する私の主な問題には対処していません。
LegendLength 2016年

8
それが目的です...
イリヤガスマン

LegendLengthなぜそれが間違っているのですか?たとえば、私のアプリケーションSettingsでは、どのウィジェットからでもアクセスできるシングルトンオブジェクトを使用しているため、各ウィジェットは表示される数値のフォーマット方法を認識しています。それがグローバルにアクセス可能なオブジェクトでない場合、コンストラクター内のすべてのウィジェットにコンストラクターに挿入し、その参照をメンバー変数として保持する必要があります。これはメモリと時間のひどい無駄です。
VK

23

シングルトンがいかに悪いかについての私の答えは常に「彼らは正しく行うのが難しい」です。言語の基本コンポーネントの多くはシングルトン(クラス、関数、名前空間、さらには演算子)であり、コンピューティングの他の側面(localhost、デフォルトルート、仮想ファイルシステムなど)のコンポーネントも同様であり、偶然ではありません。それらは時々トラブルやフラストレーションを引き起こしますが、多くのものがLOTをより良く機能させることにもなります。

私が目にする2つの最大の失敗は、グローバルのように扱うことと、シングルトンクロージャを定義できないことです。

シングルトンは基本的にグローバルなので、誰もがシングルトンをグローバルとして話します。ただし、グローバルの悪さの多く(悲しいことに、すべてではありません)は、本質的にグローバルであることからではなく、それをどのように使用するかに起因します。同じことがシングルトンにも当てはまります。実際には、「単一インスタンス」が「グローバルにアクセス可能」を意味する必要はないため、さらに多くなります。これはより自然な副産物であり、それが原因であることがわかっているすべての悪い点を考えると、グローバルアクセシビリティを利用するためにそんなに急いではいけません。プログラマは、シングルトンを見ると、常にインスタンスメソッドを介して直接アクセスしているように見えます。代わりに、他のオブジェクトと同じようにナビゲートする必要があります。ほとんどのコードは、それがシングルトン(疎結合、そうですか?)を扱っていることに気づいてさえいるべきではありません。ほんの少しのコードがグローバルであるかのようにオブジェクトにアクセスする場合、多くの害が取り消されます。

シングルトンのコンテキストも非常に重要です。シングルトンの明確な特徴は「1つだけ」があることですが、真実はある種のコンテキスト/名前空間内では「1つだけ」です。それらは通常、スレッド、プロセス、IPアドレス、またはクラスターごとに1つですが、プロセッサー、マシン、言語名前空間/クラスローダー/何でも、サブネット、インターネットなどの1つにすることもできます。

あまり一般的ではないもう1つの間違いは、シングルトンのライフスタイルを無視することです。シングルトンが1つしかないからといって、シングルトンが「常にそうであり、常にそうである」という全能であるとは限りません。また、一般的に望ましいことでもありません最も絶望的な状況で。

これらのミスを回避しても、シングルトンはPITAのままです。最悪の問題の多くが大幅に軽減されていることを確認する準備ができています。クラスローダーごとに1回(スレッドセーフポリシーが必要であることを意味する)として明示的に定義され、定義された作成メソッドと破棄メソッド、およびそれらが呼び出されるタイミングと方法を指示するライフサイクル、およびその「インスタンス」メソッドが持つJavaシングルトンを想像してください。パッケージ保護のため、通常は他の非グローバルオブジェクトを介してアクセスされます。まだトラブルの潜在的な原因ですが、間違いなくはるかに少ないトラブルです。

悲しいことに、シングルトンのやり方の良い例を教えるのではなく。私たちは悪い例を教え、プログラマーがそれらをしばらく使い切ってから、それらが悪い設計パターンであることを伝えます。


23

ウィキペディアを見るSingleton_pattern

また、過度に使用されていると感じる一部の人々によってアンチパターンと見なされ、クラスの唯一のインスタンスが実際には必要とされない状況で不要な制限が導入されます。[1] [2] [3] [4]

参照(記事からの関連参照のみ)

  1. ^アレックス・ミラー。嫌いなパターン#1:シングルトン、2007年7月
  2. ^スコット・デンスモア。シングルトンが悪である理由、2004年5月
  3. ^ Steve Yegge。シングルトンは愚かであると考えられた、2004年9月
  4. ^ JB Rainsberger、IBM。2001年7月、シングルトンを賢く使う

8
パターンについての説明は、それがなぜ悪と見なされるのかを説明していません...
Jrgns

2
あまり公平ではない:「これは、過度に使用されていると感じる一部の人々によってアンチパターンと見なされ、クラスの唯一のインスタンスが実際には必要とされない状況で不必要な制限を導入します。」参考文献を見てください...とにかくRTFMがあります。
GUI Junkie

17

シングルトン自体が悪いというわけではありませんが、GoFデザインパターンは悪いです。本当に有効な唯一の議論は、特にテストが並行して実行される場合、GoFデザインパターンがテストに関して役に立たないことです。

コードで次の手段を適用する限り、クラスの単一のインスタンスを使用することは有効な構成です。

  1. シングルトンとして使用されるクラスがインターフェースを実装していることを確認してください。これにより、同じインターフェイスを使用してスタブまたはモックを実装できます

  2. シングルトンがスレッドセーフであることを確認してください。それは当然です。

  3. シングルトンは、本質的に単純で、過度に複雑であってはなりません。

  4. アプリケーションの実行時に、シングルトンを特定のオブジェクトに渡す必要がある場合は、そのオブジェクトを構築するクラスファクトリを使用し、クラスファクトリにシングルトンインスタンスを必要なクラスに渡させます。

  5. テスト中および確定的な動作を保証するために、実際のクラス自体またはその動作を実装するスタブ/モックとして、個別のインスタンスとしてシングルトンクラスを作成し、それを必要なクラスにそのまま渡します。テスト中にシングルトンを必要とするテスト対象のオブジェクトを作成するクラスファクターを使用しないでください。オブジェクトの単一のグローバルインスタンスを渡すため、目的に反することになります。

私たちのソリューションではシングルトンを使用しており、テスト可能であり、テストの並列実行ストリームでの確定的な動作を保証する大きな成功を収めています。


+1、最後、シングルトンが有効である場合に対処する回答。
Pacerier 2014年

16

受け入れられた回答の4つのポイントに対処したいと思います。うまくいけば、誰かが私が間違っている理由を説明できれば幸いです。

  1. コードの依存関係を隠すのはなぜ悪いのですか?すでに数十の隠れた依存関係(Cランタイム呼び出し、OS API呼び出し、グローバル関数呼び出し)があり、シングルトン依存関係は簡単に見つけることができます(instance()を検索)。

    「何かをグローバルに渡さないようにすることは、コードの匂いです。」シングルトンをコードのにおいにしないようにするために、何も渡さないのはなぜですか?

    シングルトンを回避するためだけに、コールスタックで10個の関数を介してオブジェクトを渡す場合、それは素晴らしいことですか?

  2. 単一の責任の原則:これは少しあいまいで、責任の定義に依存すると思います。関連する質問は、なぜこの特定の「責任」をクラスの問題に追加するのでしょうか。

  3. オブジェクトをクラスに渡すと、そのオブジェクトをクラス内からシングルトンとして使用するよりも強く結合されるのはなぜですか?

  4. なぜ状態が続く期間が変わるのですか?シングルトンは手動で作成または破棄できるため、コントロールはそのまま残り、ライフタイムを非シングルトンオブジェクトのライフタイムと同じにすることができます。

単体テストについて:

  • すべてのクラスをユニットテストする必要はありません
  • 単体テストが必要なすべてのクラスがシングルトンの実装を変更する必要があるわけではありません
  • 彼らは場合ないユニットは、テストと実装を変更する必要性を行うことが必要が、それは依存性注入を経由して渡されたシングルトンを有することにシングルトンを使用してから、クラスを変更するのは簡単です。

1
1.これらすべての隠された依存関係? それらも悪いです。 非表示の依存関係は常に悪です。しかし、CRTとOSの場合、それらはすでに存在しており、何かを実行する唯一の方法です。(ランタイムやOSを使用せずにCプログラムを作成してみてください。)物事を行うその能力は、彼らの欠点をはるかに上回ります。コード内のシングルトンは、それほど贅沢なものではありません。それらは私たちの制御と責任の範囲内にしっかりとあるので、すべての使用(読み取り:すべての追加の非表示の依存関係)は、物事を行うための唯一の合理的な方法として正当化できるはずです。非常に、非常にそれらのいくつか実際にあります。
cHao

2.「責任」は通常「変更する理由」として定義されます。シングルトンは、その寿命の管理と実際の仕事の両方を行うことになります。ジョブの実行方法オブジェクトグラフの作成方法を変更する場合は、クラスを変更する必要があります。しかし、他のコードでオブジェクトグラフを作成し、クラスが実際に機能する場合は、その初期化コードでオブジェクトグラフを好きなように設定できます。テストダブルスを挿入してすべてを自由に分解できるため、すべてがよりモジュール化されてテスト可能になり、隠された可動部品に依存しなくなります。
cHao

1
@cHao:1.「何かを行う能力が彼らのネガティブをはるかに上回る」とあなたが認識するのは良いことです。例としては、ロギングフレームワークがあります。開発者がロギングをやめようとしているのであれば、関数呼び出しのレイヤーを介して依存性注入によってグローバルロギングオブジェクトを渡すことを義務付けるのは悪です。したがって、シングルトン。3.密結合点は、クラスのクライアントにポリモーフィズムを介して動作を制御させたい場合にのみ関連します。多くの場合そうではありません。
Jon

2
4.「手動で破棄できない」が「1つのインスタンスのみになる可能性がある」という論理的な意味があるかどうかはわかりません。それがシングルトンの定義方法である場合、同じことについて話しているわけではありません。すべてのクラス単体テストする必要はありません。これはビジネス上の決定であり、市場投入までの時間や開発コストが優先される場合があります。
Jon

1
3.ポリモーフィズムが必要ない場合は、インスタンスも必要ありません。あなたはそれを静的クラスにしたり、とにかく単一のオブジェクトと単一の実装に縛られたりするかもしれません-そして少なくともAPIはあなたにそれほど嘘をついていません。
cHao 2013

15

ビンスヒューストンには次のような基準があります。

シングルトンは、次の3つの基準がすべて満たされた場合にのみ検討する必要があります。

  • 単一インスタンスの所有権を合理的に割り当てることはできません
  • 遅延初期化が望ましい
  • 他の方法ではグローバルアクセスは提供されません

単一インスタンスの所有権、初期化がいつどのように行われるか、およびグローバルアクセスが問題にならない場合、シングルトンは十分に興味深いものではありません。


14

シングルトンは純粋主義者の観点からすると悪いです。

実用的な観点から見ると、シングルトンは開発時間と複雑さのトレードオフです。

アプリケーションがそれほど変更されないことがわかっている場合は、問題なく使用できます。要件が予期しない方法で変更された場合は、リファクタリングが必要になる場合があることを知っておいてください(ほとんどの場合、問題はありません)。

シングルトンは、単体テストを複雑にすることもあります


3
私の経験では、シングルトンから始めることは、長期的には数えませんが、短期的にもあなたを傷つけます。アプリケーションがすでに存在していて、おそらくすでに他のシングルトンが蔓延している場合は、この影響はそれほど大きくないかもしれません。ゼロから始めますか?絶対に避けてください!オブジェクトの単一インスタンスが必要ですか?このオブジェクトのインスタンス化をファクトリに管理させます。
Sven

1
AFAIKシングルトンファクトリーメソッドです。したがって、私はあなたの推薦を得ません。
tacone 2013年

3
"ファクトリ"!= "同じクラスの他の有用なものから分離できないfactory_method"
Sven

13

真に単一であるモデルの一部の側面に使用されていると想定して、パターンには本質的に問題はありません。

私は、反動がその過剰使用によるものであると私は考えています。これは、理解し、実装するのが最も簡単なパターンであるという事実によるものです。


6
反動は、対処するのが悪夢であることを認識している正式な単体テストを実践している人々ともっと関係があると思います。
ジムバーガー

1
これが-1になっている理由がわかりません。それは最も説明的な答えではありませんが、彼も間違っていません。
アウトロープログラマ

13

私は善悪の論点についてコメントするつもりはありませんが、が来て以来、それらを使用していません。依存性注入を使用すると、シングルトン、サービスロケーター、およびファクトリーに対する私の要件がほとんど取り除かれました。これは、少なくとも私が行うタイプの作業(JavaベースのWebアプリケーション)の場合、はるかに生産的でクリーンな環境だと思います。


3
デフォルトでは、Spring Beanはシングルトンではありませんか?
2010

3
ええ、でも私は「コーディング」シングルトンを意味します。私は「シングルトン」を作成していません(つまり、プライベートコンストラクターyada yada yadaをデザインパターンに従って使用しています)-はい、春では、単一のインスタンスを使用しています。
prule

4
だから他の人がそれをするとき、それは大丈夫です(私が後でそれを使うなら)が、他の人がそれをして私がそれを使わないなら、それは悪ですか?
Dainius 2014年

11

シングルトンはパターンであり、他のツールと同じように使用または乱用できます。

シングルトンの悪い部分は、一般的にユーザーです(または、シングルトンが意図されていないことにシングルトンを不適切に使用していると言うべきでしょう)。最大の違反者は、シングルトンを偽のグローバル変数として使用しています。


1
ありがとうロキ:)まさに私のポイント。魔女狩り全体が後藤の議論を思い出させる。ツールはそれらの使い方を知っている人のためのものです。気に入らないツールを使用するのは危険な場合があるので避けてください。ただし、他の人に、使用しないように、または適切に使用する方法を学ばないように指示しないでください。私は「親シングルトン」というわけではありませんが、そのようなツールがあり、それを使用するのが適切であると感じることができるという事実を気に入っています。限目。
dkellner、2015

8

ロガーやデータベース接続などのシングルトンを使用してコードを記述し、その後、複数のログまたは複数のデータベースが必要であることに気付いた場合、問題が発生します。

シングルトンは、それらから通常のオブジェクトに移動することを非常に困難にします。

また、スレッドセーフでないシングルトンを作成するのは簡単すぎます。

シングルトンを使用するのではなく、必要なすべてのユーティリティオブジェクトを関数間で渡す必要があります。次のように、それらすべてをヘルパーオブジェクトにラップすると、単純化できます。

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}

4
すべてのメソッドに引数を渡すのは素晴らしいです。APIを汚染する方法の少なくとも上位10の方法に進む必要があります。
Dainius 2014年

これは明らかな欠点であり、ネストされた呼び出しに何らかの形で伝播する引数によって言語によって処理されるべきでしたが、そのようなサポートがなければ、手動で実行する必要があります。システムクロックを表すオブジェクトのような自然なシングルトンでさえ、問題が発生する可能性があることを考慮してください。たとえば、クロックに依存するコード(複数の電気料金メーターを考える)をテストでどのようにカバーしますか?
Roman Odaisky 2014年

あなたは2リモートオブジェクトがお互いの行動に依存している場合、それは、どのように動作するかを気になぜあなたは、シングルトンをテストされていない場合は、テストしているかによって異なり、それは問題でシングルトンではないのです...
Dainius

ネストされた呼び出しに伝播する言語を提供できますか?
Dainius 2014年

1
あるモジュールが別のモジュールに依存していて、それを/ mocできないことがわからない場合は、シングルトンかどうかに関係なく困難になります。人々は継承方法を頻繁に使用していますが、そこではコンポジションを使用するべきですが、継承が悪いと言っているわけではありません。多くの人々がそこで設計ミスをしているので、OOPは絶対に避けなければなりませんか?
Dainius、2014年

8

シングルトンの問題は、スコープの拡大、したがって結合の問題です。単一のインスタンスへのアクセスが必要な状況がいくつかあり、他の方法で実現できることは否定できません。

私は現在、制御の反転(IoC)コンテナーを中心に設計し、存続期間をコンテナーによって制御できるようにしています。これにより、インスタンスに依存しているクラスが、インスタンスが1つしかないことを意識する必要がなくなります。シングルトンの寿命は将来変更される可能性があります。そのような例として、最近遭遇したのは、シングルスレッドからマルチスレッドへの簡単な調整でした。

FWIW、それを単体テストしようとしたときにPIAである場合、デバッグ、バグ修正、または拡張しようとしたときにPIAになります。



7

シングルトンは悪くありません。グローバルにユニークではない何かをグローバルにユニークにするのは悪いことです。

ただし、「アプリケーションスコープサービス」(コンポーネントを相互作用させるメッセージングシステムについて考えてください)があります。これは、シングルトンを呼び出す「MessageQueue」-メソッド「SendMessage(...)」を持つクラスです。

その後、どこからでも以下を実行できます。

MessageQueue.Current.SendMessage(new MailArrivedMessage(...));

そしてもちろん、次のようにします。

MessageQueue.Current.RegisterReceiver(this);

IMessageReceiverを実装するクラス内。


6
また、スコープが小さい2番目のメッセージキューを作成する場合は、コードを再利用して作成することを許可すべきではないのはなぜですか。シングルトンはそれを防ぎます。しかし、通常のメッセージキュークラスを作成し、「アプリケーションスコープ」インスタンスとして機能する1つのグローバルインスタンスを作成した場合、他の用途のために2番目のインスタンスを作成できます。ただし、クラスをシングルトンにした場合、2番目のメッセージキュークラスを作成する必要があります。
39:39

1
また、MessageQueueなどのどこからでも適切に呼び出すことができるように、グローバルCustomerOrderListだけを用意する必要がないのはなぜですか。答えはどちらも同じだと思います。グローバル変数を効果的に作成しています。
LegendLength 2016年

7

スレッドセーフではないオブジェクトをシングルトンパターンに配置する人が多すぎます。DataContextはスレッドセーフではなく、純粋に作業単位オブジェクトであるにもかかわらず、シングルトンパターンで実行される DataContext(LINQ to SQL)の例を見てきました。


多くの人が安全でないマルチスレッドコードを記述していますが、それはスレッドを排除する必要があるということですか?
Dainius 2014年

@ダイニウス:実際、はい。IMOの既定の同時実行モデルはマルチプロセスである必要があり、2つのプロセスが(1)互いにメッセージを簡単にやり取りしたり、(2)必要に応じてメモリを共有したりすることができます。スレッド化は、すべてを共有したいが、本当に共有したくない場合に便利です。アドレス空間全体を共有することでエミュレートできますが、これもアンチパターンと見なされます。
cHao

@Dainius:そしてもちろん、それは正直から善への並行性がまったく必要であると想定しています。多くの場合、OSが他のことをするのを待つ間、1つのことを実行できるようにすることだけが必要です。(たとえば、ソケットからの読み取り中にUIを更新します。)適切な非同期APIを使用すると、大多数のケースでフルオンスレッド化が不要になる場合があります。
cHao

あなたが処理する必要があること、データの巨大な行列を、持っている場合、多くの人にその間違った操作を行う可能性があるため、そう、それは、シングルスレッドであることを行う方が良いでしょう...
Dainius

@Dainius:多くの場合、そうです。(ミックスに同期を追加すると、スレッド化によって実際に速度が低下する可能性があります。これは、マルチスレッド化がほとんどの人の最初の考えではない理由の主な例です。)他の場合では、2つのプロセスが必要なもの。もちろん、プロセスがメモリを共有するように調整する必要があります。しかし率直に言って、私はそれを良いことだ思います-少なくとも、デフォルトですべて共有モードにするよりもはるかに良いです。共有する部分、つまりスレッドセーフにする必要のある部分を明示的に(そして理想的には、知って)言う必要があります。
cHao

6

シングルトンについて、まだ誰も言っていないことがもう1つあります。

ほとんどの場合、「単一性」は、そのインターフェースの特性ではなく、あるクラスの実装の詳細です。コントロールコンテナを反転すると、この特性がクラスユーザーから見えなくなる場合があります。クラスをシングルトン(@Singletonたとえば、Javaのアノテーションを使用)としてマークする必要があるだけです。残りはIoCCが行います。アクセスは既にIoCCによって管理されているため、シングルトンインスタンスへのグローバルアクセスを提供する必要はありません。したがって、IoCシングルトンに問題はありません。

IoCシングルトンの反対のGoFシングルトンは、getInstance()メソッドを介してインターフェースに「単一性」を公開することになっているため、上記のすべてに影響を受けます。


3
私の意見では、「単一性」はランタイム環境の詳細であり、クラスコードを作成したプログラマはこれを考慮すべきではありません。むしろ、それはクラスUSERによってなされる考慮事項です。実際に必要なインスタンスの数を知っているのはUSERだけです。
Earth Engine

5

シングルトンはありません、あなたがそれを使用する場合、悪適切に最小限に。ある時点でシングルトンの必要性に取って代わる、他にも多くの優れた設計パターンがあります(そして最良の結果も得られます)。しかし、一部のプログラマーはこれらの良いパターンを認識せず、すべてのケースでシングルトンを使用しているため、シングルトンは悪人になっています。


驚くばかり!完全に同意します!しかし、もっと詳しく説明することもできますし、すべきです。最も一般的に無視されているデザインパターンの拡大や、シングルトンを「適切かつ最小限に」使用する方法などです。より簡単よりも言っ行わ!:P
cregox 2013年

基本的に、代替手段は、グローバル状態を介してオブジェクトにアクセスするのではなく、メソッドパラメータを介してオブジェクトを渡すことです。
LegendLength 2016年

5

まず、クラスとその共同作業者は、扶養家族に焦点を当てるのではなく、最初に意図した目的を実行する必要があります。ライフサイクル管理(インスタンスが作成されたとき、およびスコープから外れたとき)は、クラスの責任の一部であってはなりません。このために受け入れられているベストプラクティスは、依存関係注入を使用して依存関係を管理する新しいコンポーネントを作成または構成することです。

多くの場合、ソフトウェアはより複雑になり、状態の異なるシングルトンクラスの複数の独立したインスタンスを持つことは理にかなっています。そのような場合、シングルトンを単に取得するためのコードをコミットすることは間違っています。Singleton.getInstance()小さな単純なシステムでは使用しても問題ないかもしれませんが、同じクラスの別のインスタンスが必要な場合は機能しません。

クラスをシングルトンと見なすべきではありませんが、それは、その使用法または依存関係を構成するためにどのように使用されるかを適用したものでなければなりません。迅速で厄介な問題の場合、これは問題ではありません。ハードコーディングを行うだけでファイルパスは問題にならないと言うだけですが、大きなアプリケーションでは、このような依存関係を除外して、DIを使用してより適切な方法で管理する必要があります。

テストでシングルトンが引き起こす問題は、ハードコードされた単一の使用例/環境の症状です。テストスイートと多くのテストはそれぞれ個別のものであり、シングルトンのハードコーディングと互換性のないものを分離しています。


4

それらは基本的にオブジェクト指向のグローバル変数であるため、通常、それらを必要としないようにクラスを設計できます。


クラスが1回のインスタンスに限定されていない場合は、セマフォによって管理されるクラスに静的メンバーが必要になります。代替案は何ですか?
Jeach

「MainScreen」を備えた巨大なアプリケーションがあります。この画面は、多くの小さいモーダル/非モーダルウィンドウ/ UIフォームを開きます。私見MainScreenはシングルトンである必要があると思うので、たとえば、アプリケーションの隅にあるウィジェットがMainScreenのステータスバーにそのステータスを表示したい場合、MainScreen.getInstance()。setStatus( "Some Text"); 代替案として何を提案しますか?アプリケーション全体でMainScreenを渡しますか?:D
サルヴィンフランシス

2
@SalvinFrancis:私がお勧めするのは、気にする必要のないものを気にするオブジェクトの作成をやめ、アプリをこっそりといじり回すことです。:)あなたの例はイベントではるかにうまくいきます。イベントを正しく行うと、ウィジェットはMainScreenがあるかどうかを気にする必要さえありません。それは単に「ちょっと、起こった」とブロードキャストし、「起こった」イベントにサブスクライブしたものすべて(MainScreen、WidgetTest、またはその他すべて)が応答方法を決定します。それがOOPがとにかく行われることになっている方法です。:)
cHao 2013

1
@Salvin MainScreenが多くのコンポーネントによって「サイレント」に更新されている場合、MainScreenについてデバッグすることがどれほど難しいかを検討してください。あなたの例は、シングルトンが悪い理由として完璧です。
LegendLength 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.