静的クラスとシングルトンパターンの間には、どんな本当の(すなわち実用的な)違いがありますか?
どちらもインスタンス化なしで呼び出すことができ、どちらも「インスタンス」を1つだけ提供し、どちらもスレッドセーフではありません。他に違いはありますか?
シングルトンメソッドとスタティックメソッドのどちらもスレッドセーフではないと言う理由は何ですか?通常、両方の はスレッドセーフであるように 実装されるべきです。
シングルトンと多数の静的メソッドの大きな違いは、シングルトンはインターフェースを実装できる(または私の経験ではあまり一般的ではありませんが、役に立つ基本クラスから派生する)ことができるということです。 "実装。
真の答えはJon Skeetによるものです。 ここで別のフォーラムに参加しています 。
シングルトンは単一の作成されたインスタンスへのアクセスを許可します - そのインスタンス(あるいはむしろそのインスタンスへの参照)は他のメソッドへのパラメータとして渡され、通常のオブジェクトとして扱われることができます。
静的クラスは静的メソッドのみを許可します。
interface
を実装することはできますが、クラスの静的メソッド(またはC#static class
など)は実装できません。シングルトンパターンは、静的クラスに比べていくつかの利点があります。まず、シングルトンはクラスを拡張してインタフェースを実装できますが、静的クラスはできません(クラスを拡張できますが、そのインスタンスメンバを継承しません)。通常、静的クラスは最初のロード時に初期化されるため、シングルトンは遅延的または非同期的に初期化される可能性があり、クラスローダの問題が発生する可能性があります。ただし、最も重要な利点は、インスタンスが1つしかないとユーザーに想定させることなく、シングルトンを多態的に処理できることです。
static
クラスは、状態を必要とするものには適していません。たくさんの関数、つまりMath
(またはプロジェクトではUtils
)をまとめるのに便利です。そのため、クラス名は、関数を見つけるための手掛かりを与えるだけで、それ以上のものはありません。
Singleton
は私のお気に入りのパターンで、私はそれを使って一点で何かを管理します。 static
クラスよりも柔軟性があり、その状態を維持できます。それはインターフェースを実装し、他のクラスから継承し、継承を許可することができます。
static
とsingleton
の間で選択するための私のルール:
まとめておく必要がある関数がたくさんある場合は、static
が選択です。いくつかのリソースへの単一アクセスを必要とする他のものはすべて、singleton
として実装できます。
静的クラス: - /
静的クラスのインスタンスは作成できません。
クラスを含むプログラムまたは名前空間が読み込まれるときに、.NET Framework共通言語ランタイム(CLR)によって自動的に読み込まれます。
静的クラスはコンストラクタを持つことができません。
静的クラスをmethodに渡すことはできません。
StaticクラスをC#の別のStaticクラスに継承することはできません。
すべての静的メソッドを持つクラス。
より良いパフォーマンス(静的メソッドはコンパイル時に結び付けられます)
シングルトン: - /
オブジェクトのインスタンスを1つ作成して再利用できます。
ユーザーが要求したときに、シングルトンインスタンスが初めて作成されます。
シングルトンクラスはコンストラクタを持つことができます。
シングルトンクラスのオブジェクトを作成してmethodに渡すことができます。
シングルトンクラスは継承の制限を何も言いません。
シングルトンクラスのオブジェクトは配置できますが、静的クラスのオブジェクトは配置できません。
メソッドはオーバーライドできます。
必要に応じて遅延ロードすることができます(静的クラスは常にロードされます)。
インターフェースを実装できます(静的クラスはインターフェースを実装できません)。
静的クラスは静的メソッドのみを持つクラスであり、そのためのWordは「関数」になります。静的クラスで具体化されたデザインスタイルは、純粋に手続き型です。
一方、SingletonはOO designに固有のパターンです。それは、オブジェクトのインスタンスであり(多相など、その固有の可能性はすべてあります)、その特定の役割のインスタンスがその存続期間全体にわたって1つだけ存在することを保証する作成手順を持ちます。
シングルトンパターンでは、シングルトンを派生型のインスタンスとして作成できますが、静的クラスではできません。
簡単な例:
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
Jon Skeet's Answer に展開するには/ /
シングルトンと多くの静的メソッドの大きな違いは、シングルトンはインターフェースを実装できる(またはあまり一般的ではありませんが、便利な基本クラスから派生できる)ことです。
シングルトンは、クラスを単体テストするときに扱いやすくなります。シングルトンをパラメータ(コンストラクタ、セッター、またはメソッド)として渡す場所はどこでも、代わりにシングルトンのモックバージョンまたはスタブバージョンを代用することができます。
シングルトンのもう1つの利点は、シリアライズが容易にシリアル化できることです。これは、その状態をディスクに保存するか、リモートでどこかに送信する必要がある場合に必要になることがあります。
メソッドをオーバーライドすることはできませんが、メソッド非表示を使用することはできます。 ( Javaに隠れているメソッドとは何ですか?JavaDocの説明でも混乱を招きます )
public class Animal {
public static void foo() {
System.out.println("Animal");
}
}
public class Cat extends Animal {
public static void foo() { // hides Animal.foo()
System.out.println("Cat");
}
}
まとめると、utilメソッドを保持するためには静的クラスを使用し、それ以外のすべてにはSingletonを使用します。
編集
静的クラスも遅延ロードされます。ありがとう@jmoreno( 静的クラスの初期化はいつ行われますか? )
静的クラスに対するメソッドの非表示ありがとう@MaxPeng。
私は偉大なOO理論家ではありませんが、私が知っていることから、シングルトンと比較して静的クラスに欠けている唯一のOO機能は多態性です。あなたがそれを必要としないのであれば、静的クラスではもちろん継承(インターフェースの実装についてはわからない)やデータと関数のカプセル化を持つことができます。
「静的クラスで具体化されたデザインスタイルは単なる手続き型です」とモレンディルのコメントは間違っているかもしれませんが、私は同意しません。静的メソッドでは、静的メンバーにアクセスできます。これは、シングルトンメソッドがそれらの単一インスタンスメンバーにアクセスするのとまったく同じです。
編集:
もう1つの違いは、スタティッククラスはプログラムの開始時に インスタンス化 され、プログラムの有効期間全体にわたって存続しますが、シングルトンはある時点で明示的にインスタンス化されるということです。破壊することもできます。
*または言語によっては、最初の使用時にインスタンス化されることもあります。
Loggerが静的クラスであった場合、Jonのポイントを説明するために以下に示すことはできません。クラスSomeClass
はILogger
実装のインスタンスがそのコンストラクタに渡されることを期待しています。
シングルトンクラスは依存性注入が可能であるために重要です。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var someClass = new SomeClass(Logger.GetLogger());
}
}
public class SomeClass
{
public SomeClass(ILogger MyLogger)
{
}
}
public class Logger : ILogger
{
private static Logger _logger;
private Logger() { }
public static Logger GetLogger()
{
if (_logger==null)
{
_logger = new Logger();
}
return _logger;
}
public void Log()
{
}
}
public interface ILogger
{
void Log();
}
}
シングルトンはISがインスタンス化した通常のクラスですが、クライアントコードから間接的に1回だけです。静的クラスはインスタンス化されません。私が知っている限りでは、静的メソッド(静的クラスは静的メソッドを持たなければならない)は非静的よりも高速です。
編集する
FxCopパフォーマンスルールの説明: "インスタンスデータにアクセスしたり、インスタンスメソッドを呼び出したりしないメソッドは、静的(VBでは共有)としてマークできます。そうすると、コンパイラはこれらのメンバーに非仮想呼び出しサイトを発行します。現在のオブジェクトポインタがnullではないことを保証する呼び出しごとに実行時にチェックを行わないようにすると、パフォーマンスに敏感なコードのパフォーマンスが大幅に向上する可能性があります。 "
これが静的クラスの静的メソッドにも当てはまるかどうかは実際にはわかりません。
Singletonはインスタンス化されています。インスタンス化されたインスタンスは1つだけなので、Singletonでは single になります。
静的クラスは、それ自身以外のものによってインスタンス化することはできません。
私はこの定義に同意します:
「 single 」という単語は、アプリケーションのライフサイクル全体で単一のオブジェクトを意味するため、適用範囲はアプリケーションレベルです。
static にはObjectポインタがないため、有効範囲はApp Domainレベルです。
さらに、両方ともスレッドセーフになるように実装する必要があります。
あなたはについての他の興味深い違いを見つけることができます。 シングルトンパターンとスタティッククラス
シングルトンはテストの観点からはより良いアプローチです。静的クラスとは異なり、シングルトンはインターフェースを実装することができ、あなたはモックインスタンスを使用してそれらを注入することができます。
以下の例では、これを説明します。メソッドgetPrice()を使用するメソッドisGoodPrice()があり、シングルトンのメソッドとしてgetPrice()を実装するとします。
getPrice機能を提供するシングルトン:
public class SupportedVersionSingelton {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
// calculate price logic here
return 0;
}
}
GetPriceの使い方
public class Advisor {
public boolean isGoodDeal(){
boolean isGoodDeal = false;
ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
int price = supportedVersion.getPrice();
// logic to determine if price is a good deal.
if(price < 5){
isGoodDeal = true;
}
return isGoodDeal;
}
}
In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it.
public interface ICalculator {
int getPrice();
}
最後のシングルトン実装:
public class SupportedVersionSingelton implements ICalculator {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
return 0;
}
// for testing purpose
public static void setInstance(ICalculator mockObject){
if(instance != null ){
instance = mockObject;
}
テストクラス:
public class TestCalculation {
class SupportedVersionDouble implements ICalculator{
@Override
public int getPrice() {
return 1;
}
}
@Before
public void setUp() throws Exception {
ICalculator supportedVersionDouble = new SupportedVersionDouble();
SupportedVersionSingelton.setInstance(supportedVersionDouble);
}
@Test
public void test() {
Advisor advidor = new Advisor();
boolean isGoodDeal = advidor.isGoodDeal();
Assert.assertEquals(isGoodDeal, true);
}
}
GetPrice()を実装するために静的メソッドを使用する代わりの方法を取った場合、getPrice()をモックするのは困難でした。あなたはパワーモックで静的にモックすることができました、しかしすべての製品がそれを使うことができるというわけではありません。
主な違いは以下のとおりです。
1つの注目すべき違いは、シングルトンに付随する異なるインスタンス化です。
静的クラスでは、それはCLRによって作成され、私たちはそれを制御しません。シングルトンでは、オブジェクトはアクセスしようとした最初のインスタンスでインスタンス化されます。
バックエンドに接続するDBフレームワークがあります。複数のユーザーにわたるダーティリードを避けるために、シングルトンパターンを使用して、いつでも単一のインスタンスを使用できるようにしました。
C#では、静的クラスはインタフェースを実装できません。単一のインスタンスクラスが業務契約またはIoCの目的でインタフェースを実装する必要がある場合は、ここで静的クラスなしでSingletonパターンを使用します。
シングルトンは、ステートレスシナリオで状態を維持する方法を提供します。
あなたに役立つことを願っています..
多くの場合、特にシングルトンインスタンスが決して変化しないか非常にゆっくりと変化する場合、これら2つは実際的な違いはありません。保持構成.
最大の違いは、シングルトンが特殊な静的専用Javaクラスとは対照的に通常のJava Beanであることです。そしてこのため、シングルトンはもっと多くの状況で受け入れられます。実際のところ、これはデフォルトのSpring Frameworkのインスタンス化戦略です。消費者は、それが受け渡されているシングルトンであることを知らないかもしれませんし、普通のJava Beanのように扱うだけです。 Springでよく見られるように、要件が変更され、シングルトンが代わりにプロトタイプになる必要がある場合は、消費者に一連のコードを変更することなく完全にシームレスに実行できます。
他の誰かが、静的クラスは純粋に手続き型であるべきだと先に述べました。 Java.lang.Math。私の考えでは、そのようなクラスは決して渡されるべきではなく、静的なfinal以外のものを属性として持つべきではありません。それ以外のすべてについては、シングルトンを使用してください。シングルトンのほうがはるかに柔軟で保守が簡単です。
私は以下を読み、それも理にかなっていると思います:
ビジネスの世話をして
覚えておいて、最も重要なOO規則の1つは、オブジェクトがそれ自体に責任があるということです。つまり、クラスのライフサイクルに関する問題は、静的などの言語構成要素に委任するのではなく、クラス内で処理する必要があります。
本反対論の思想プロセス第4版から。
私が書いた記事の中で、シングルトンが静的クラスよりはるかに優れている理由についての私の見解を説明しました。
シングルトンクラスのオブジェクトを作成してmethodに渡すことができます。
シングルトンクラスには継承の制限はありません。
静的クラスのオブジェクトを配置することはできませんが、クラスをシングルトンにすることはできます。
a。直列化 - 静的メンバーはそのクラスに属しているため、直列化できません。
b。コンストラクターを非公開にしましたが、静的メンバー変数は依然としてサブクラスに渡されます。
c。すべてがクラスのロード時にのみロードされるため、遅延初期化はできません。
クライアントの観点からは、静的な振る舞いはクライアントに知られていますが、シングルトンの振る舞いはクライアントから隠されて完了することができます。クライアントは、彼が何度も何度もプレイしているインスタンスが1つしかないことを決して知っていないかもしれません。
単一の静的クラス instance(つまり、静的変数または大域変数であるクラスの単一インスタンス)と 単一の静的ポインタ ヒープ上のクラス:
アプリケーションが終了すると、静的クラスインスタンスのデストラクタが呼び出されます。つまり、その静的インスタンスをシングルトンとして使用した場合、シングルトンは正しく機能しなくなりました。そのシングルトンを使用するコードがまだ別のスレッドなどで実行されている場合、そのコードはクラッシュする可能性があります。
Javaの static class には静的メソッドしかありません。それは機能のコンテナです。それは手続き型プログラミング設計に基づいて作成されています。
シングルトンクラス はオブジェクト指向設計のパターンです。 Singletonクラスは、JVM内のオブジェクトのインスタンスを1つだけ持ちます。このパターンは、JVMにそのクラスのインスタンスが常に1つだけ存在するように実装されています。
フル機能のクラスが欲しいときメソッドや変数はたくさんありますが、シングルトンを使用します。
1つか2つのメソッドしか持たないクラスが必要な場合は、 MailServiceクラスには、SendMail()というメソッドが1つだけあります。静的クラスとメソッドを使用します。
私の頭の違いは、オブジェクト指向プログラミング(Singleton/Prototype)または関数型プログラミング(Static)の実装です。
私たちが焦点を当てるべきであるということが結局私たちがオブジェクトを持つということであるとき、私たちはシングルトンパターンによって作成されたオブジェクトの数にあまりにも焦点を合わせています。他の人がすでに言ったように、それは拡張することができ、パラメータとして渡すことができますが、最も重要なことには、それはステートフルです。
一方、静的は関数型プログラミングを実装するために使用されます。静的メンバーはクラスに属します。彼らは無国籍です。
ところで、シングルトンの静的クラスを作成できることを知っていましたか:)
静的クラスと非静的シングルトンクラスの違いを理解したように、静的はC#ではインスタンス化されていない「型」であり、シングルトンは真の「オブジェクト」です。つまり、静的クラスのすべての静的メンバーはその型に割り当てられますが、Singletonではオブジェクトの下に格納されます。ただし、静的クラスは構造型のような値型ではないため、参照型のように動作します。
つまり、シングルトンを作成すると、クラス自体は静的ではありませんが、そのメンバは静的なので、自分自身を参照するシングルトン内の静的メンバは、それ自体の中空の「型」ではなく実際の「オブジェクト」に関連付けられます。そのような種類のものは、静的シングルトンと非静的シングルトンの他の機能とメモリ使用量を超えた違いを明確にしています。
どちらもメンバーの単一コピーである静的メンバーを使用しますが、シングルトンは静的メンバーに加えてアドレスが存在する実際のインスタンス化された「オブジェクト」を囲むように参照メンバーをラップします。そのオブジェクト自体はinを受け渡して参照することができ、値を追加することができるという特性を持っています。 Staticクラスは単なる型なので、その静的メンバを指す以外には存在しません。その概念の種類は、継承やその他の問題を超えて、シングルトン対スタティッククラスの目的を固めました。
静的クラスの例
public class Any {
private static Any instance = new Any();
private Singleton() {
System.out.println("creating");
}
}
シングルトンパターンの場合は1つのインスタンスしか存在しません。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
System.out.println("creating");
if (instance != null) {
throw new RuntimeException("Imposible create a new instance ");
}
}
}