クラスのインスタンスを単一化して、いつどのような時に呼び出されても
インスタンスを新しく作成することなく同じアドレスを返してくれるデザイン方法を言います。
その具現にはいくつか方法があります。
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; }
}
上記のコードでインスタンスの作成時点のみ変えてみました。
これで初期値設定などはできます。
しかし、使用していない時にも作られる問題はまだ残っています。
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; }
}
形だけ変わっただけで、メモリーに無駄ができる点は同じです。
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の処理は順次的に処理するため、パフォーマンスの低下は避けられません。
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の中ならどこからでもアクセスが可能ですし
リフレクション攻撃から安全です。
댓글 없음:
댓글 쓰기