單例模式是比較簡單的一個模式,項目中也經常用得到。
實現細節
將類的構造方法設置爲私有的(private),通過個公有的(public)的方法來獲取類的實例。
代碼示例
public class Singleton {
private static Singleton singleton= null;
public static Singleton getSingleton(){
if(singleton==null){
singleton = new Singleton();
}
return singleton;
}
private Singleton(){
//System.out.println("new singleton");
}
}
上邊的這個例子在高併發的情況下可能會出現同步問題,如果一個線程在完成if判斷但是對象未能創建完成的時候另一個線程也進行if判斷,那麼內存中就會產生多個實例,爲了保證線程安全,可以採用以下兩種方法。
第一種做法,直接實例化類
public class Singleton {
private static Singleton singleton= new Singleton();
public static Singleton getSingleton(){
return singleton;
}
private Singleton(){
//System.out.println("new singleton");
}
}
第二種方法,對if判斷加鎖
public class ConcurrentSingleton {
private static ConcurrentSingleton singleton = null;
private ConcurrentSingleton(){
//System.out.println("new singleton");
}
public static ConcurrentSingleton getSingleton(){
if(singleton==null){
createSingleton();
}
return singleton;
}
private static synchronized void createSingleton() {
if(singleton==null){
singleton = new ConcurrentSingleton();
}
}
}
單例模式的優缺點
優點是在內存中只存在一個實例,減少內存開銷和創建、銷燬對象的性能損耗,可以避免對資源的多種佔用,優化和共享資源訪問。
缺點是擴展比較困難。
單例模式的擴展
如果一個類只能生成限定個數的實例,可以通過擴展單例來實現
代碼實例
public class MultiInstanceSingleton {
private static int maxInstanceSize = 5;
private int number = 0;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
private static Vector<MultiInstanceSingleton> vec = new Vector<MultiInstanceSingleton>();
private MultiInstanceSingleton(){
}
private MultiInstanceSingleton(int num){
this.number = num;
}
private static synchronized MultiInstanceSingleton createInstance(){
return new MultiInstanceSingleton(vec.size());
}
public static MultiInstanceSingleton getInstance(){
MultiInstanceSingleton instance = null;
if(vec.size()<maxInstanceSize){
instance = createInstance();
vec.add(instance);
}else{
int num = new Random().nextInt(maxInstanceSize);
instance = vec.elementAt(num);
}
return instance;
}
public void doSomething(){
System.out.println("我是"+this.number+"號");
}
public static void main(String[] args) {
for(int i=0;i<50;i++){
getInstance().doSomething();
}
}
}