静的クラスとシングルトンパターンの間に実際の(つまり、実用的な)違いは何ですか?
どちらもインスタンス化せずに呼び出すことができ、どちらも「インスタンス」を1つだけ提供し、どちらもスレッドセーフではありません。他に違いはありますか?
singleton
、static
メソッドが単なる関数であり、非OOエンティティであるオブジェクトです。
静的クラスとシングルトンパターンの間に実際の(つまり、実用的な)違いは何ですか?
どちらもインスタンス化せずに呼び出すことができ、どちらも「インスタンス」を1つだけ提供し、どちらもスレッドセーフではありません。他に違いはありますか?
singleton
、static
メソッドが単なる関数であり、非OOエンティティであるオブジェクトです。
回答:
シングルトンメソッドまたは静的メソッドのいずれかがスレッドセーフではないとはどういう意味ですか?通常、両方がすべきスレッドセーフになるように実装するがあります。
シングルトンと一連の静的メソッドの大きな違いは、シングルトンがインターフェイスを実装できる(または、私の経験ではそれほど一般的ではないが、有用な基本クラスから派生できる)ため、シングルトンを「別のちょうど」のように渡すことができることです。 "実装。
Foo
メソッドがあるFoo
とします。この設定により、呼び出し元はシングルトンを実装として使用することを選択できます。または、別の実装を使用することもできます。この方法はシングルトンから切り離されています。クラスに静的メソッドしかない状況と比較してください。これらのメソッドを呼び出す必要のあるすべてのコードは、静的メソッドを含むクラスを指定する必要があるため、クラスに密結合されています。
本当の答えは、ここの別のフォーラムでの Jon Skeetによるものです。
シングルトンは、作成された単一のインスタンスへのアクセスを許可します。そのインスタンス(または、そのインスタンスへの参照)は、パラメーターとして他のメソッドに渡し、通常のオブジェクトとして扱うことができます。
静的クラスは静的メソッドのみを許可します。
interface
シングルトンクラスでが、クラスの静的メソッド(またはC#などstatic class
)できません。シングルトンパターンには、静的クラスに比べていくつかの利点があります。まず、シングルトンはクラスを拡張してインターフェースを実装できますが、静的クラスはできません(クラスを拡張することはできますが、インスタンスメンバーを継承しません)。シングルトンはレイジーまたは非同期で初期化できますが、静的クラスは通常、最初にロードされたときに初期化されるため、クラスローダーの問題が発生する可能性があります。ただし、最も重要な利点は、シングルトンは、ユーザーにインスタンスが1つしかないと想定させることなく、ポリモーフィックに処理できることです。
static
クラスは、状態を必要とするもののためのものではありません。たくさんの機能をまとめるMath
(つまりUtils
プロジェクトで)のに便利です。したがって、クラス名は、関数を見つけるための手がかりを与えるだけで、それ以上のものはありません。
Singleton
は私のお気に入りのパターンであり、私はそれを使用して何かを一元的に管理します。static
クラスよりも柔軟性があり、状態を維持できます。インターフェイスを実装し、他のクラスから継承し、継承を許可できます。
static
とを選択するための私のルールsingleton
:
まとめておくべき機能がたくさんある場合は、それstatic
が選択です。いくつかのリソースへの単一のアクセスを必要とする他のものは、として実装できますsingleton
。
State
通常、時間とともに変化するオブジェクトのさまざまなプロパティの組み合わせです。Googleで正式な定義を行うことができます。
静的クラス:-
静的クラスのインスタンスは作成できません。
クラスを含むプログラムまたは名前空間が読み込まれると、.NET Framework共通言語ランタイム(CLR)によって自動的に読み込まれます。
静的クラスはコンストラクタを持つことができません。
静的クラスをメソッドに渡すことはできません。
StaticクラスをC#の別のStaticクラスに継承することはできません。
すべての静的メソッドを持つクラス。
パフォーマンスの向上(静的メソッドはコンパイル時に結合されます)
シングルトン:-
オブジェクトのインスタンスを1つ作成して再利用できます。
シングルトンインスタンスは、ユーザーが要求したときに初めて作成されます。
シングルトンクラスはコンストラクタを持つことができます。
シングルトンクラスのオブジェクトを作成してメソッドに渡すことができます。
シングルトンクラスは継承の制限を何も言いません。
シングルトンクラスのオブジェクトは破棄できますが、静的クラスは破棄できません。
メソッドはオーバーライドできます。
必要なときに遅延ロードできます(静的クラスは常にロードされます)。
インターフェイスを実装できます(静的クラスはインターフェイスを実装できません)。
静的クラスとは、静的メソッドのみを持つクラスであり、「関数」の方がいいでしょう。静的クラスに組み込まれたデザインスタイルは、純粋に手続き型です。
一方、シングルトンは、OOデザインに固有のパターンです。これは、オブジェクトのインスタンスであり(ポリモーフィズムなど、それに固有のすべての可能性があります)、その存続期間全体でその特定の役割のインスタンスが1つしかないことを保証する作成手順があります。
シングルトンパターンでは、派生型のインスタンスとしてシングルトンを作成できますが、静的クラスでは作成できません。
簡単な例:
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
ジョン・スキートの回答を拡張するには
シングルトンと多くの静的メソッドの大きな違いは、シングルトンがインターフェイスを実装できる(またはIMEとしては一般的ではないものの、有用な基本クラスから派生できる)ため、シングルトンを「別の」実装であるかのように渡すことができることです。
シングルトンは、クラスをユニットテストするときに扱いやすくなります。シングルトンをパラメーター(コンストラクター、セッター、またはメソッド)として渡す場所はどこでも、代わりにシングルトンのモックバージョンまたはスタブバージョンを置き換えることができます。
MySingleton mockOfMySingleton = mock(MySingleton.class)
。
new ClazzToTest(mockSingleton);
ここに良い記事があります:http : //javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html
メソッドをオーバーライドすることはできませんが、メソッドの非表示を使用できます。(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メソッドを保持するために静的クラスのみを使用し、それ以外にはすべてシングルトンを使用します。
編集
静的クラスも遅延読み込みされます。@jmorenoに感謝します(静的クラスの初期化はいつ行われますか?)
静的クラスのメソッド隠蔽。@MaxPengに感謝します。
Animal animal = new Cat();
なりanimal.foo();
ますか?
私は優れたOO理論家ではありませんが、静的クラスがシングルトンと比較して欠けている唯一のOO機能は多態性だと私は知っています。しかし、それが必要ない場合は、静的クラスを使用すると、継承(インターフェースの実装については不明)およびデータと関数のカプセル化を使用できます。
モレンディルのコメント「静的クラスに組み込まれたデザインスタイルは純粋に手続き型です」間違っているかもしれませんが、私はそうは思いません。静的メソッドでは、静的メンバーにアクセスできます。これは、単一インスタンスメンバーにアクセスするシングルトンメソッドとまったく同じです。
編集:
私は実際に今、別の違いは静的クラスがインスタンス化されるということだと考えていますプログラムの開始時にれ*、プログラムの全寿命を通じて存続するますが、シングルトンはある時点で明示的にインスタンス化され、破棄することもできます。
*または言語によっては、最初の使用時にインスタンス化される場合があると思います。
ジョンのポイントを説明するために、ロガーが静的クラスで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();
}
}
シングルトンはインスタンス化された通常のクラスですが、クライアントコードから間接的に一度だけです。静的クラスはインスタンス化されません。私の知る限り、静的メソッド(静的クラスには静的メソッドが必要)は非静的メソッドより高速です。
編集:
FxCopパフォーマンスルールの説明:「インスタンスデータにアクセスしたり、インスタンスメソッドを呼び出したりしないメソッドは、静的としてマークできます(VBで共有)。これにより、コンパイラーはこれらのメンバーに非仮想呼び出しサイトを発行し、現在のオブジェクトポインターがnull以外であることを保証する各呼び出しについて、実行時にチェックします。これにより、パフォーマンスに依存するコードの測定可能なパフォーマンスが向上する場合があります。場合によっては、現在のオブジェクトインスタンスへのアクセスの失敗が正確性の問題を表すことがあります。 "
これが静的クラスの静的メソッドにも当てはまるかどうかは、実際にはわかりません。
シングルトンはインスタンス化されます。インスタンス化されたインスタンスが1つしかないため、シングルトンのシングルになります。
静的クラスは、それ自体以外ではインスタンス化できません。
シングルトンは、テストの観点からはより良いアプローチです。静的クラスとは異なり、シングルトンはインターフェイスを実装でき、モックインスタンスを使用してそれらを挿入できます。
以下の例でこれを説明します。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によって作成され、制御できません。シングルトンの場合、オブジェクトは、アクセスしようとした最初のインスタンスでインスタンス化されます。
多くの場合、特にシングルトンインスタンスが変更されないか、非常にゆっくりと変更される(例:構成を保持する)場合、これら2つには実際的な違いはありません。
最大の違いは、シングルトンがまだ特殊な静的専用Javaクラスとは対照的な通常のJava Beanであることです。このため、シングルトンはより多くの状況で受け入れられます。実際、これはデフォルトのSpring Frameworkのインスタンス化戦略です。消費者は、それが渡されたシングルトンであることを知っている場合も知らない場合もあり、通常のJava Beanのように扱います。要件が変更され、シングルトンが代わりにプロトタイプになる必要がある場合、Springでよく見られるように、コンシューマーにコードを変更することなく、完全にシームレスに実行できます。
他の誰かが、静的クラスは純粋に手続き型である必要があると前述しました(例:java.lang.Math)。私の考えでは、このようなクラスは渡されるべきではなく、属性としてstatic final以外のものを保持してはなりません。それ以外の場合は、シングルトンを使用してください。シングルトンの方がはるかに柔軟性があり、保守が容易です。
バックエンドに接続するDBフレームワークがあります。複数のユーザーにまたがるダーティリードを回避するために、シングルトンパターンを使用して、単一のインスタンスをいつでも使用できるようにしました。
C#では、静的クラスはインターフェイスを実装できません。単一のインスタンスクラスがビジネスコントラクトまたはIoCの目的でインターフェイスを実装する必要がある場合、ここで静的クラスなしのシングルトンパターンを使用します
シングルトンは、ステートレスシナリオで状態を維持する方法を提供します
お役に立てれば幸いです。
a。シリアル化-静的メンバーはクラスに属しているため、シリアル化できません。
b。コンストラクターをプライベートにしましたが、静的メンバー変数は引き続きサブクラスに渡されます。
c。すべてがクラスのロード時にのみロードされるため、遅延初期化を行うことはできません。
クライアントの観点からは、静的な動作はクライアントに知られていますが、シングルトンの動作はクライアントから隠して完了することができます。クライアントは、何度も何度も遊んでいるインスタンスが1つしかないことを知ることはありません。
私が書いた記事では、シングルトンが静的クラスよりもはるかに優れている理由について私の見解を説明しました。
シングルトンクラスのオブジェクトを作成してメソッドに渡すことができます。
シングルトンクラスには継承の制限はありません。
静的クラスのオブジェクトを破棄することはできませんが、シングルトンクラスは破棄できます。
JDKには、シングルトンと静的の両方の例があり、一方でjava.lang.Math
は静的メソッドを持つ最後のクラスでjava.lang.Runtime
あり、他方ではシングルトンクラスです。
シングルトンの利点
シングルトンパターンよりも状態を維持する必要がある場合は、静的クラスよりも優れた選択肢です。静的クラスで状態を維持すると、特に並行環境でバグが発生するため、複数のスレッドによる適切な同期並列変更なしに競合状態が発生する可能性があります。
シングルトンクラスは、重いオブジェクトであれば遅延ロードできますが、静的クラスにはそのような利点はなく、常に積極的にロードされます。
シングルトンを使用すると、継承とポリモーフィズムを使用して基本クラスを拡張し、インターフェースを実装して、さまざまな実装を提供できます。
Javaの静的メソッドはオーバーライドできないため、柔軟性に欠けます。一方、シングルトンクラスで定義されたメソッドは、拡張することでオーバーライドできます。
静的クラスの欠点
静的クラスの利点
それぞれの詳細な説明は冗長すぎるので、良い記事へのリンクを張るだけです - シングルトンについて知りたいすべてのこと
単一の静的クラスインスタンス(つまり、たまたま静的変数またはグローバル変数であるクラスの単一インスタンス)と、ヒープ上のクラスのインスタンスへの単一の静的ポインターとの間には、大きな違いがあります。
アプリケーションが終了すると、静的クラスインスタンスのデストラクタが呼び出されます。つまり、その静的インスタンスをシングルトンとして使用した場合、シングルトンは正しく機能しなくなります。そのシングルトンを使用するコードがまだ実行されている場合(たとえば、別のスレッドで)、そのコードはクラッシュする可能性があります。
私の頭の違いは、オブジェクト指向プログラミング(シングルトン/プロトタイプ)または関数型プログラミング(静的)の実装です。
注目すべきは、最終的にオブジェクトを保持することである場合、シングルトンパターンによって作成されたオブジェクトの数に焦点を合わせすぎています。他の人がすでに言ったように、それは拡張することができ、パラメータとして渡されますが、最も重要なことはそれはステートフルです。
一方、staticは関数型プログラミングの実装に使用されます。静的メンバーはクラスに属しています。彼らは無国籍です。
ところで、シングルトンスタティッククラスを作成できることをご存知でしたか:)
getInstance()
するたびにメソッドを呼び出すオーバーヘッドがあるため、効率が低下する可能性があります(ほとんどの場合、問題ではありません)。