Android中單例的使用

Singleton是一種創建型模式,指某個類采用Singleton模式,則在這個類被創建后,只可能產生一個實例供外部訪問,并且提供一個全局的訪問點。
  核心知識點如下:
  1.將采用單例設計模式的類的構造方法私有化(采用private修飾)。
  2.在其內部產生該類的實例化對象,并將其封裝成private static類型。
  3.定義一個靜態方法返回該類的實例。

單例創建的幾種方式

/**
 * 方法一
 * 餓漢模式、線程安全 但效率比較低 
 */
public class CommonData {

    /**
     * 私有化構造防止外部創建
     */
    private CommonData() {}

    // 將自身的實例對象設置為一個屬性,并加上Static和final修飾符
    private static final CommonData mInstance = new CommonData ();

   // 靜態方法返回該類的實例
    public static CommonData getInstance() {
        return mInstance;
    }
}

注解:方法一的優點是簡單不存在多線程同步問題、缺點是可能會耗費內存

/**
 * 方法二
 * 懶漢模式、非線程安全  
 */
public class CommonData {

    /**
     * 私有化構造防止外部創建
     */
    private CommonData() {}

    // 定義一個類型的變量(不初始化,注意這里沒有使用final關鍵字)
    private static CommonData mInstance;

   // 定義一個靜態的方法(調用時再初始化,但是多線程訪問時,可能造成重復初始化問題)
    public static CommonData getInstance() {
       if (mInstance == null) {
             mInstance = new CommonData();
         }
        return mInstance;
    }
}

注解:方法二優點是某些條件下會節約內存、缺點并發時會出現多個實例

/**
 * 方法三
 * 懶漢模式、線程安全簡單實現   
 */
public class CommonData {

    /**
     * 私有化構造防止外部創建
     */
    private CommonData() {}

    // 定義一個類型的變量(不初始化,注意這里沒有使用final關鍵字)
    private static CommonData mInstance = null;

   // 定義一個靜態的方法(調用時再初始化,使用synchronized 避免多線程訪問時,可能造成重的復初始化問題)
    public static synchronized  CommonData getInstance() {
       if (mInstance == null) {
             mInstance = new CommonData();
         }
        return mInstance;
    }
}

注解:方法三優點是使用synchronized關鍵字避免多線程訪問時出現多個實例、缺點是同步方法頻繁調用時,效率略低。

/**
 * 方法四 單例模式最優方案
 * 懶漢模式、線程安全并且效率高   
 */
public class CommonData {

    /**
     * 私有化構造防止外部創建
     */
    private CommonData() {}

    // 定義類型的變量(不初始化,不使用final關鍵字,使用volatile保證了多線程訪問時instance變量的可見性,避免了instance初始化時其他變量屬性還沒賦值完時,被另外線程調用)
    private static volatile CommonData mInstance = null;

   // 定義一個靜態的方法
    public static CommonData getInstance() {
       // 對象實例化時與否判斷(不使用同步代碼塊,instance不等于null時,直接返回對象,提高運行效率)
       if (mInstance == null) {
             //同步代碼塊(對象未初始化時,使用同步代碼塊,保證多線程訪問時對象在第一次創建后,不再重復被創建)
             synchronized  (CommonData.class){
                 //未初始化,則初始instance變量
                 if(mInstance == null){
                     mInstance = new CommonData();
                 }
             }     
         }
        return mInstance;
    }
}

注解:方法四為單例模式的最佳實現。內存占用地,效率高,線程安全,多線程操作原子性

什么是單例且創建的幾種方式上述已經講完,接下來說下在android 單例模式的實際應用:

在android中使用單例模式最常見的方式是用來存儲程序中用到的數據,即在打開應用時保存一些全局使用的臨時數據方便隨時隨地獲取使用,且在android中使用單例來存儲全局變量(臨時數據)幾乎不存在并發問題,所以在android中我們使用方法三的模式就可以了。下面給個簡單的例子說明下:(在打開應用時我們就獲取一些參數作為全局變量以待其它地方隨時調用如:手機的唯一標識、型號、系統版本號等、也可以用來保存登錄信息方便使用)

/**
 * 公共數據類定義,用于存儲程序中用到的數據
 * @author zcq
 * Created by 2016/3/7.
 */
public class CommonData {

    /**
     * 私有化構造防止外部創建
     */
    private CommonData() {}

    private static CommonData mInstance = null;

    /**
     * 獲取公共數據類實例
     * @return 返回公共數據類實例
     */
    public synchronized static CommonData getInstance() {
        if (mInstance == null) {
            mInstance = new CommonData();
        }
        return mInstance;
    }

    /**
     * 登陸者信息
     * 添加時間:2016-10-25
     */
    private User loginer;

    /**
     * 給登陸者賦值
     * @param user
     */
    public void setLoginer(User user){
        this.loginer = user;
    }

    /**
     * 獲取登陸者信息
     * @return
     */
    public User getLoginer(){
        return this.loginer;
    }

    /**
     * 檢查用戶是否已登錄
     * @return 若已登錄則返回 true,否則返回 false
     */
    public boolean isLogined(){
        return loginer != null;
    }

  //手機mac
    public String mac;

    /**
     * 設置獲取到的手機Mac
     * @param mac
     */
    public void setMac(String mac){
        this.mac = mac;
    }

    /**
     * 獲取手機Mac
     * @return
     */
    public String getMac(){
        return mac;
    }

  //手機IMEI
    public String IMEI;

    /**
     * 設置獲取到的手機IMEI
     * @param imei
     */
    public void setImei(String imei){
        this.IMEI = imei;
    }

    /**
     * 獲取手機IMEI
     * @return
     */
    public String getImei(){
        return IMEI;
    }

    //手機型號
    public String phoneModel;

    /**
     * 設置獲取到的手機型號
     * @param phoneModel
     */
    public void setPhoneModel(String phoneModel){
        this.phoneModel = phoneModel;
    }

    /**
     * 獲取手機型號
     * @return
     */
    public String getPhoneModel(){
        return  phoneModel;
    }
}

希望本文章能給您帶去幫助,感謝您的閱讀!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容