單例模式 - 確定 N 先生的GrilFriend

codeGoogle發表於2018-03-16

一、GrilFriendClass 引言

N 先生很快就要大學畢業,大學四年忙於學(網)業(遊),也沒有找個女朋友。每每回家,家人都催促他趕快談一個,或者乾脆說要直接給 N 先生介紹物件。 有句話說什麼樣的年齡就該做什麼樣的事情,這句話放在當下還是很有道理的。可是 N 先生心中對成家立業是有自己的認識的,認為先立業而後成家,自己都沒條件過平凡的日子怎麼給另一半想要的生活呢。     但是由於家裡催的緊,N 先生就想到了租女友先應付家裡的姑姑阿姨們。

於是這一年每逢過節回家,N 先生都會帶新物件回家,     這年端午節,N 先生租安琪拉回家了,家裡人都誇著說 N 的物件看著很乖巧,

我們都知道這裡 N 的物件就是指的安琪拉。

同年中秋節,N 先生租孫尚香回家了,家裡人都誇著說 N 的物件像個大小姐。

我們都知道這裡 N 的物件就是指的孫尚香。

又到國慶節,N 先生租蔡文姬回家了,家裡人都誇著說 N 的物件十分卡哇伊。

我們都知道這裡 N 的物件就是指的蔡文姬。

這一年來,家人沒見到 N 先生時都會誇 N 的物件,但每次誇的物件都不一樣,這裡不是同一個物件。

當全域性系統每需要呼叫某個類 N 時,需要建立一個類 N 的新物件,即便建立的物件名稱相同,也不是同一個物件。

終於,畢業後的 N 先生在合適的年齡遇到了真愛不知火舞,確定了自己唯一的物件,這幾趟回家,家裡人提及 N 先生的物件時,都讚不絕口說大學生活不錯。

我們都知道,畢業後大家提到的 N 的物件都是不知火舞。這裡是同一個物件。

在軟體工程單例模式思想出來之前,每當開發者使用某個類時都會新建一個物件例項使用,優秀的開發者會在使用結束後釋放掉物件佔用的資源,單一般開發過程中很少在意這一點。於是這些沒被釋放資源的物件就成為了Java 虛擬機器裡的垃圾。單例模式就是保證了系統全域性只存在唯一的一個例項物件。確定了唯一物件的 N 先生,也代表了畢業前後 N 先生更加的成熟。

二、GrilFriendSingleton 例項演示

2-1 GrilFriendUnSingleton 非單例模式例項

在單例模式之前,我們會這樣寫一個Class ,寫基本屬性和類的相關方法,及建構函式或者帶引數的建構函式。下面以預設構造方法為例程式碼演示

package pers.niaonao.entity;

/**
 * @author niaonao
 * 非單例模式下的基本類
 */
public class GrilFriendUnSingleton {

	//預設的構造方法
	public GrilFriendUnSingleton() {
	}
	
	private String info = "我是你的新 GrilFriend";
	
	/**
	 * 獲取物件資訊的方法
	 * @return
	 */
	public String getGrilFriend() {
		return info;
	}
} 
複製程式碼

通過新建該類的實體物件來呼叫相關方法

 package pers.niaonao.test;

import pers.niaonao.entity.GrilFriendUnSingleton;

/**
 * @author niaonao
 * 
 */
public class TestGrilFriend {

	public static void main(String[] args) {
		
		//對實體類建立兩個物件
		GrilFriendUnSingleton n_first_grilfriend = new GrilFriendUnSingleton();
		GrilFriendUnSingleton n_next_grilfriend = new GrilFriendUnSingleton();
		
		String info = "n_first_grilfriend 和 n_next_grilfriend";
		
		//判斷物件是否是同一個例項
		if (n_first_grilfriend != n_next_grilfriend) {
			info += "\n\t不是同一個例項,是兩個不同的物件:"
					+ "\n\t魔法為我而存在," + n_first_grilfriend.getGrilFriend()
					+ "\n\t大小姐駕到," + n_next_grilfriend.getGrilFriend();
		} else {
			info += "\n\t是同一個例項,同一個物件:"
					+ "\n\t會用不知火流的烈焰燒死你的呦," + n_first_grilfriend.getGrilFriend()
					+ "\n\t會用不知火流的烈焰燒死你的呦," + n_next_grilfriend.getGrilFriend();
		}
		
		System.out.println(info);
	}
}<span style="font-size:14px"></span><span style="color:#000000"></span>

複製程式碼

程式執行結果如下:

我們在系統全域性每需要使用該類時,都會在使用該類的地方通過構造方法新建類的實體物件。所以就會出現在系統全域性內,存在多個當前類的物件,並且其他地方就使用一次就不使用了,新建了一個物件佔用了一定的資源,但沒有釋放資源,這就造成資源的浪費,也是系統垃圾的一種。

image

2-2 GrilFriendBySingleton 單例模式例項

使用單例模式去寫一個class

package pers.niaonao.entity;  
  
/** 
 * @author niaonao 
 * 單例模式下的基本類 
 */  
public class GrilFriendBySingleton {  
  
    //初始化靜態私有變數grilfriend  
    private static GrilFriendBySingleton grilfriend = null;  
      
    /** 
     * 構造單例模式基本方法getInstance() 
     * 呼叫該方法,會先判斷物件grilfriend是否不為null,即物件是否已存在, 
     * 若例項物件已存在則不再建立新物件,否則建立一個新物件給變數grilfriend。 
     *  
     * 保證當前類只存在一個實體物件。即單例模式 
     * @return grilfriend 
     */  
    public static GrilFriendBySingleton getInstance() {  
  
        if (null == grilfriend)  
            grilfriend = new GrilFriendBySingleton();  
  
        return grilfriend;  
    }  
      
    //預設的構造方法  
    public GrilFriendBySingleton() {  
    }  
      
    private String info = "我是你的新 GrilFriend";  
      
    /** 
     * 獲取物件資訊的方法 
     * @return 
     */  
    public String getGrilFriend() {  
        return info;  
    }  
}  
複製程式碼

測試類 TestGrilFriend 來測試單例模式

 public static void main(String[] args) {  
          
        //通過單例模式建立出兩個實體常量  
        GrilFriendBySingleton n_first_grilfriend = GrilFriendBySingleton.getInstance();  
        GrilFriendBySingleton n_next_grilfriend = GrilFriendBySingleton.getInstance();  
          
        String info = "n_first_grilfriend 和 n_next_grilfriend";  
          
        //判斷物件是否是同一個例項  
        if (n_first_grilfriend != n_next_grilfriend) {  
            info += "\n\t不是同一個例項,是兩個不同的物件:"  
                    + "\n\t魔法為我而存在," + n_first_grilfriend.getGrilFriend()  
                    + "\n\t大小姐駕到," + n_next_grilfriend.getGrilFriend();  
        } else {  
            info += "\n\t是同一個例項,同一個物件:"  
                    + "\n\t會用不知火流的烈焰燒死你的呦," + n_first_grilfriend.getGrilFriend()  
                    + "\n\t會用不知火流的烈焰燒死你的呦," + n_next_grilfriend.getGrilFriend();  
        }  
          
        System.out.println(info);  
    }  
複製程式碼

程式執行結果如下:

即使對 GrilFriendBySingleton 建立了兩個變數,但通過單例模式保證是同一個例項,即在記憶體中是存放在一個位置的一個物件。保證了系統全域性內只存在唯一的一個例項。這就是單例模式

image

三、Singleton Pattern 單例模式

通過前兩部分,應該對單例模式有一定的理解及認識,並能運用單例在實際開發中。下面說一下單例模式的定義,意義。

3-1 定義

Ensure a class only has one instance,and provide a global point of access to it.

GOF 對單例模式的定義是,保證一個類只有一個例項存在,同時提供能對該例項加以訪問的全域性訪問方法。

3-2 類圖

image

3-3 三要素

  • 必須保證一個類只能有一個例項

  • 必須是這個類自行建立這個例項

  • 必須自行向整個系統提供這例項

3-4.優缺點

使用單例模式必然要了解其優缺點。

  • 優點

客戶端使用單例模式類的例項,只需要呼叫一個單一的方法即可生成唯一的例項,節約了資源。

  • 缺點

單例模式難以實現序列化 Serialization,所以採用單例模式的類很難被持久化,也不易通過網路傳輸,一般網路傳輸資料都會序列化物件相關的類。

單例模式採用靜態方法 static,不支援物件導向的三大特性之一的繼承,無法再繼承結構extend 中使用。

如果分散式叢集的環境下存在多個 Java 虛擬機器,不易確定具體的哪個單例在執行。

3-5 應用場景

一般會在Util 工具類中 service服務類中使用,部分entity 類中。

在多執行緒之間,公用同一個資源或操作同一個物件,這時候就用單例模式;在系統全域性都會使用到的,共享資源,全域性變數,可以使用單例模式;之所以說部分 entity 實體類會使用單例模式,是因為在大規模系統中,考慮到效能節約物件的建立時間,會使用單例模式。

3-6 說明

上面的GrilFriendBySingleton 實現中,我們通過getInstance() 保證只有一個例項存在,通過關鍵字 static 修飾getInstance() 方法,提供全域性訪問的方法。

我們得通過GrilFriendBySingleton 提供的方法去獲取單例,讓類自己建立例項,不能通過構造方法new GrilFriendBySingleton()再去建立,這就違背了單例模式的建立初衷。

3-7 標準單例程式碼演示

最後標準單例模式程式碼演示:

public class Singleton {  
    private static Singleton uniqueInstance = null;  
   
    private Singleton() {  
       // Exists only to defeat instantiation.  
    }  
   
    public static Singleton getInstance() {  
       if (uniqueInstance == null) {  
           uniqueInstance = new Singleton();  
       }  
       return uniqueInstance;  
    }  
    // Other methods...  
}  
複製程式碼

原文連結:http://blog.csdn.net/niaonao/article/details/79500198

更多

 一招教你讀懂JVM和Dalvik之間的區別

NDK專案實戰—高仿360手機助手之解除安裝監聽

最新2017(Android)面試題級答案(精選版)

相信自己,沒有做不到的,只有想不到的

微信公眾號:終端研發部

技術+職場

相關文章