Post Page Advertisement [Top]



シングルトンとは?

クラスのインスタンスを単一化して、いつどのような時に呼び出されても

インスタンスを新しく作成することなく同じアドレスを返してくれるデザイン方法を言います。


その具現にはいくつか方法があります。


1. Public final フィールド利用

public class NutrtionFacts {
    private String name = "name";
    public static final NutrtionFacts INSTANCE = new NutrtionFacts();
    private NutrtionFacts(){}

    public void setName(String name)
    { this.name = name; }
    public String getName()
    { return name; }
}


public class Main {
    public static void main(String[] args) {
    NutrtionFacts nutrtionFacts = NutrtionFacts.INSTANCE;
    NutrtionFacts nutrtionFacts2 = NutrtionFacts.INSTANCE;

    nutrtionFacts.setName("あいうえお");
    System.out.print(nutrtionFacts2.getName());
    }
}


nutrtionFactsの名前を変えたらnutrtionFacts2の名前も変わることが見れます。

コンストラクタをprivateを使って閉じ、変わりにstatic変数を作る方法です


この方法の利点は非常に簡単で使いやすい。
しかし、使用していない時にもStatic変数が作られてメモリーの無駄が生じます。

また、変数の作成と同時にインスタンスが生成されるため、
インスタンスの初期値の設定などが不可能です。



2. static 利用

public class NutrtionFacts {
    private String name = "name";
    public static final NutrtionFacts INSTANCE;
    static {
        // 設定
        INSTANCE = new NutrtionFacts();
        // 設定
    }
    private NutrtionFacts(){}

    public void setName(String name)
    { this.name = name; }
    public String getName()
    { return name; }
}

上記のコードでインスタンスの作成時点のみ変えてみました。

これで初期値設定などはできます。
しかし、使用していない時にも作られる問題はまだ残っています。



3. Staticファクトリーを利用


public class NutrtionFacts {
    private String name = "name";
    public static final NutrtionFacts INSTANCE = new NutrtionFacts();
    private NutrtionFacts(){}
    public static NutrtionFacts getInstance(){
        return INSTANCE;
    }

    public void setName(String name)
    { this.name = name; }
    public String getName()
    { return name; }
}

Staticメソッド度を一つ作って、そのメソッドを使用して返す方法です。

形だけ変わっただけで、メモリーに無駄ができる点は同じです。


4. IF文

public class NutrtionFacts {
    private String name = "name";
    public static NutrtionFacts INSTANCE;
    private NutrtionFacts(){}
    public static NutrtionFacts getInstance(){
        if(INSTANCE==null){
             INSTANCE = new NutrtionFacts();
        }
        return INSTANCE;
    }

    public void setName(String name)
    { this.name = name; }
    public String getName()
    { return name; }
}

getInstanceメソッドが呼び出された時にインスタンスを生成します。

しかし、欠点が存在します。
この場合、スレッドの競合が生じるかも知れません。なので

public static synchronized NutrtionFacts getInstance(){
    if(INSTANCE==null){
         INSTANCE = new NutrtionFacts();    }
    return INSTANCE;}

このようにsynchronized処理する手もありますが、
synchronizedの処理は順次的に処理するため、パフォーマンスの低下は避けられません。


5. enum クラスの利用

public enum  NutrtionFacts {
    INSTANCE;
    private String name = "name";
    public static NutrtionFacts getInstance(){
        return INSTANCE;
    }

    public void setName(String name)
    { this.name = name; }
    public String getName()
    { return name; }
}

イペクチブJavaではのenumクラスを利用する方法が一番いい方法だと語っています。

まず、このクラスは、直列化(シリアライズ)がいくら複雑に行われるとしても
一つのインスタンスを確保します。
また、マルチスレッドを使用する場合競合の心配がありません。

また、enumバリューはJavaの中ならどこからでもアクセスが可能ですし
リフレクション攻撃から安全です。

댓글 없음:

댓글 쓰기

Bottom Ad [Post Page]

| Designed by Colorlib