序文
シングルトンデザインパターンは、クラスの唯一のグローバルインスタンスがあることを確認します。コンストラクタは、(あなたはまだ呼び出すためにリフレクションを使用することができますが)呼び出しを防ぐために、プライベートとして宣言されています。クラスのクラスの静的インスタンスを宣言し、インスタンスを取得するためのパブリックメソッドを宣言します。このブログは、やるシングルトンを使用することのデメリットを整理する方法の簡単な実装、スレッドセーフな分析を提供します。
スレッドセーフ
一つのスレッドセーフなメソッドは、クラスがロードされたときに、このメンバーを初期化し、Javaランタイムライブラリは、このメソッドを使用することです。
方法2は、スレッドセーフではありません。機能(クリティカルセクション)への複数のスレッド場合、それは別のインスタンスの数を返します。
コード検証
次のコードは、それが真実を保証することはできません第二のマルチスレッド方式の場合で、スレッドセーフ検証される「シングルトンを。」各クラスを印刷して表示ハッシュコードは、クラスのインスタンスは一意ではありません。
class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
try {
Thread.sleep(233);
singleton = new Singleton();
}
catch (Exception e) {
e.printStackTrace();
}
}
return singleton;
}
}
public class Main {
public static void main(String args[]) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
public void run() {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.hashCode());
}
}).start();
}
}
}
ソリューション
単純なアプローチは、各スレッドがクリティカルセクションに入るのを待っているので、同期低効率として宣言するgetInstanceすることです。
もう一つの方法は、ダブルロック(DCL)のチェックと呼ばれ、一般的な変数は、(あなたはこの変数を使用するたびに、各スレッドは、この変数の変化を見ることができることを保証するために、メモリから取り出された)volatile宣言しました。
class Singleton {
private volatile static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
try {
Thread.sleep(233);
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return singleton;
}
}
害
だから、悪いものを、グローバル変数が間違っている、このデザインパターンを非難しないでください。
1、グローバル変数
公共資源のシングルトン管理は、どこかのコードでは、単に読んで、これらのパブリックリソースに書き込むことができ、あなたがシングルトンのインスタンスを取得することができ、シングルトンのインスタンスを取得するメソッドを呼び出します。これは、シングルトンは、グローバル変数になったことができます。
グローバル変数を害する、シングルトンは欠点も。シナリオと独自のグローバル変数のグローバル変数の利点の使用は、彼らは何も言わないしたくないグローバル変数の欠点について話どこ双方は、見て分離します。
[2]私たちが見たの下に非常に興味深い同様に、グローバル変数の欠点を分析する前に:
誰かが彼のお尻をそれを突き出すすることを決定しますときに、しかし、あなたが知っていることはできません - あなたの仲間のプログラマーとのグローバルな状態を使用すると、お友達と同じ歯ブラシを使用してのようなものです。
私はおそらく歯ブラシの匂いがそれを使用し、男はこの観点を言いたいです。なぜそれでグローバル変数の使用を抑制するために一緒に人々を規制しませんか?
グローバル変数の性質のために男のポイントは、誰もがプログラム全体は大きな不確実性をもたらしている、何かをするためにそれを使用することができます。非常に悪いではないが、以下は、いくつかのコンパイル害に関するオンライン議論は、多くのグローバル変数、:
- 符号の結合度が高いです。一部の機能は、グローバル状態変数に依存していると仮定し、これらの機能は、グローバル変数によって一緒に連結されています。別の関数を読んだ上でプレゼンス変更機能の効果は、これらの機能は、事実上、一緒にリンクされています。
- 難しいテストします。いくつかの州で保存されたグローバル変数は、あなたは正しいテストを実行することができ、モジュールの順序を調整する必要があります。しかしながら、テストユニットではなくシーケンシャルよりも、互いに独立しなければなりません。
- マルチスレッドの書き込み、相互に排他的に。
- これは、関数の入力と出力の機能を破壊します。出力を書き込み、入力を読み取るために、グローバル変数を取ります。
- 競合を命名。
- 読みやすさを減らします。機能を理解するために、また、あなたは、グローバル変数のインとアウトを追跡するために使用する必要があります。
2、単一責任の原則を弱体化させます
定義:カテゴリでは、それが唯一の変更点の一つの原因でなければなりません
クラスはシングルトン時間を使用すると、それだけではなく、このクラスを担当して、タスクを完了する必要があり、また、単一のオブジェクトリソースの作成と管理を担当しています。このクラスの機能は、2つのタスクを実行、相関が低いです。
これは本当にあまりにも悪いことではありません。結局のところ、設計原理は、常に実行する必要はありません。
使い分け
欠点上述したように、コアの本質は、シングルトンは、グローバル変数として使用を避けることです。それはどのようなシングルトンの使用シナリオのですか?
バック役割の性質アップシングルトン、このクラスの唯一のインスタンス。このデザインパターンの前で話すことなぜなら、このインスタンスを管理する必要性、単一責任の原則を損ないます。
これは2つの理由から、このデザインパターンの使用に沸きます:
(1)単一のインスタンス
例の管理(2)
彼は、[1]にシングルトンを使用しての具体的な例を語りました。これは、ログ(ログ)です。機能ログの本質とログを開くかどうかに、コード結合を生成しないが、システムの機能にあまり影響されないため。
参考リンク
- https://stackoverflow.com/questions/228164/on-design-patterns-when-should-i-use-the-singleton
- https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil
- https://stackoverflow.com/questions/26285520/implementing-singleton-with-an-enum-in-java
- https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons?page=1&tab=votes#tab-top