讀秦小波《設計模式之禪》 -- 單例模式

BruceZhang發表於2015-01-01

      新年第一天,在這裡首先要祝大家新年快樂!

      這篇文章中,介紹的是非常重要,也是非常常用的一種設計模式 -- 單例模式。例如,我們在電腦上登入QQ的時候,同一個QQ號碼就只能登入一次,而不可能出現一個號碼可以登入兩次的情況;再好像我現在聽歌用的播放器,我也只能開啟它一次,當它在執行的時候,我不能夠同時執行兩個播放器客戶端。。。等等的這些模式都是單例的,即它能保證一個類就只有一個例項物件。

      這裡運用書中的例子去解釋構造單例的方法。

      一個國家需要有一個皇帝,並且這個皇帝就只能有一個,那麼,很顯然,它是單例的。我們需要構造一個皇帝類,且這個皇帝類只能有一個例項物件,那麼,這裡就會出現一個限制,即這個類的構造方法需要是私有的(private),否則,我們可以任意的生成物件。且這個類需要有一個靜態方法(static),當我們需要這個類的物件時,就可以利用這個方法去獲取類物件。

      好吧,看下具體的實現吧:

public class __Q_Y_Emperor {

	/*這樣設計可以保證它是執行緒安全的*/
	private static __Q_Y_Emperor _Emperor = new __Q_Y_Emperor();
	
	private __Q_Y_Emperor()
	{
		
	}
	
	public static __Q_Y_Emperor __Q_Y_GetInstance()
	{
		return _Emperor;
	}
	
	public static void __Q_Y_Talk()
	{
		System.out.println("i am Qinyi Zhang...");
	}
}
      這個類的實現就是利用到單例模式,當然,這裡只是單例模式的一種實現方式。

      我們需要一個測試函式,測試下這個單例模式是否好用,這裡,場景是有幾個大臣找皇帝,然後,每一個大臣找到的都是同一個皇帝。

public class __Q_Y_EmperorMain {

	/**
	 * @param args
	 */
	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int _Minister = 5;
		
		for (int i = 0; i != _Minister; ++i)
		{
			/*獲取的例項物件都是同一個*/
			__Q_Y_Emperor _Emperor = __Q_Y_Emperor.__Q_Y_GetInstance();
			
			_Emperor.__Q_Y_Talk();
		}
	}

}
      我們執行下這個主函式,得到如下的結果:

i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
      下面,看下類圖是怎樣的,很簡單,沒有繼承關係之類的


      書中從單例模式又引申出了一個叫 “多例模式” 的設計方法,即一個類能產生多個物件,但是物件的個數是有限制的。

      也同樣是皇帝的例子,只是這個例子中出現了多個皇帝,每個大臣可能找到的是不同的皇帝。

      好吧,這個也是很容易實現的:

public class __Q_Y_MultiEmperor {

	private final static int _MaxNumOfEmperor = 3;
	
	private static ArrayList<String> _EmperorName = new ArrayList<String>();
	
	private static ArrayList<__Q_Y_MultiEmperor> _EmperorList = new ArrayList<>();
	
	private static int _CurrentNumOfEmperor = 0;
	
	private __Q_Y_MultiEmperor()
	{
		
	}
	
	private __Q_Y_MultiEmperor(String _name)
	{
		_EmperorName.add(_name);
	}
	
	static
	{
		/*多例模式,物件個數是有限制的*/
		for (int i = 0; i != _MaxNumOfEmperor; ++i)
		{
			_EmperorList.add(new __Q_Y_MultiEmperor("num " + (i + 1)));
		}
	}
	
	public static __Q_Y_MultiEmperor __Q_Y_GetInstance()
	{
		Random _randrom = new Random();
		
		_CurrentNumOfEmperor = _randrom.nextInt(_MaxNumOfEmperor);
		
		return _EmperorList.get(_CurrentNumOfEmperor);
	}
	
	public static void __Q_Y_Talk()
	{
		System.out.println(_EmperorName.get(_CurrentNumOfEmperor));
	}
}
      測試函式:

public class __Q_Y_MultiMain {
	
	/**
	 * @param args
	 */
	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int _Minister = 10;
		
		for (int i = 0; i != _Minister; ++i)
		{
			__Q_Y_MultiEmperor _Emperor = __Q_Y_MultiEmperor.__Q_Y_GetInstance();
			
			_Emperor.__Q_Y_Talk();
		}
		
	}

}
      類圖:


      最後,執行下這個例子吧:

num 3
num 2
num 2
num 2
num 3
num 1
num 2
num 2
num 1
num 1



相關文章