1. 程式人生 > >設計模式(一):單例模式 java實現

設計模式(一):單例模式 java實現

參考:http://blog.csdn.net/jason0539/article/details/23297037/

單例模式:指的是一個類只有一個例項物件。它的設計是為了實現類的單一功能。專注於自己的事情。

有如下三個特點:

  1. 單例類只有一個例項
  2. 單例類必須自己建立這一個例項
  3. 單例類必須將自己的這個例項提供給其他物件

因此我們在實現單例類的時候要注意一下幾點:

  1. 首先禁止他人建立例項物件,故它的建構函式必須是私有的;
  2. 其次自己建立例項要在類載入時建立,故必須有一個靜態的例項物件的成員變數;
  3. 要給他人提供例項,故要有一個獲取該方法的公有成員方法。

常見的單例模式的實現有5中方法

  1. 懶漢式:需要時建立例項,執行緒不安全
  2. 餓漢式:類載入時就建立,執行緒不安全
  3. 使用同步方法的懶漢式
  4. 使用雙重檢查加鎖的懶漢式
  5. 使用靜態內部類的懶漢式(這個比較推薦)

下面將一一實現:

一、懶漢式

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //測試方法
    public void sayHello(String name){
        System.out.println("Hello, "
+ name); } /** * 執行緒不安全的寫法 * @return */ public static Singleton1 getInstance(){ if(instance == null){ instance = new Singleton1(); } return instance; } }

測試:

public class TestSingleton1 {


    public static void main(String[] args){

        Singleton1 ins = Singleton1.getInstance();

        ins.sayHello("Mike"
); Singleton1 ins2 = Singleton1.getInstance(); ins2.sayHello("Mike"); if(ins == ins2){ System.out.println("同一個例項"); }else{ System.out.println("不同的例項"); } }

二、餓漢式

public class Singleton2 {

    private Singleton2(){

    }

    private static Singleton2 instance = new Singleton2();

    private static Singleton2 getInstance(){
        return instance;
    }
}

三、懶漢式+同步機制

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //測試方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    public static synchronized Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }

        return instance;
    }
}

四、懶漢式+雙重檢查鎖定

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //測試方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    public static Singleton1 getInstance(){
        if(instance == null){

            synchronized(Singleton1.class){
                if(instance == null){
                    instance = new Singleton1();
                }
            }
        }

        return instance;
    }
}

五、懶漢式+靜態內部類

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //測試方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    private static class LazyHolder{
        private static final Singleton1 INSTANCE = new Singleton1();
    }
    public static Singleton1 getInstance(){
        return LazyHolder.INSTANCE;
    }
}

六、登記式單例類

package designpattern.singleton;

import java.util.HashMap;
import java.util.Map;


/**
 * 登記式單例模式
 * @author wenbaoli
 *
 */
public class Singleton3 {

    private static Map<String, Singleton3> map = new HashMap<String, Singleton3>();

    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);

    }

    //保護的預設構造子
    protected Singleton3(){}

    //靜態工廠方法,返回此類唯一的例項
    public static Singleton3 getInstance(String name){
        if(name == null){
            name = Singleton3.class.getName();
            System.out.println("name == null" + "---> name = " + name);
        }

        if(map.get(name) == null){
            try{
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            }catch(InstantiationException e){
                e.printStackTrace();
            }catch(IllegalAccessException e){
                e.printStackTrace();
            }catch(ClassNotFoundException e){
                e.printStackTrace();
            }
        }

        return map.get(name);
    }

    //一個示意性的商業方法
    public String about(){
        return "Hello, I am RegSingleton.";
    }

    public static void main(String[] args){
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }

}

測試:

public class TestSingleton3 {


    public static void main(String[] args){


        Singleton3 single1 = Singleton3.getInstance(null);

        System.out.println(single1.about());

        System.out.println("------------我是分割線----------");
        Singleton3 single2 = Singleton3.getInstance(single1.getClass().getName());

        System.out.println(single1.about());

        if(single1 == single2){
            System.out.println("他們是同一個例項");
        }else{
            System.out.println("他們是不同的例項");
        }
    }

}

附錄:查漏補缺——程式碼中我不熟悉或不知道的事

  1. name = Singleton3.class.getName(); : 表示獲取Singleton3這個類的名字。一個類的name是它所在的包名.類名
  2. (Singleton3) Class.forName(name).newInstance() : 表示去載入name(包名.類名)的下的這個類。。。

例如:給你一個字串變數,它代表一個類的包名和類名,你怎麼例項化它?只有你提到的這個方法了,不過要再加一點。 A a = (A)Class.forName(“pacage.A”).newInstance(); 這和你 A a = new A(); 是一樣的效果。