讀秦小波《設(shè)計(jì)模式之禪》 -- 單例模式
來源:程序員人生 發(fā)布時(shí)間:2015-01-04 08:54:43 閱讀次數(shù):3369次
新年第1天,在這里首先要祝大家新年快樂!
這篇文章中,介紹的是非常重要,也是非常經(jīng)常使用的1種設(shè)計(jì)模式 -- 單例模式。例如,我們?cè)陔娔X上登錄QQ的時(shí)候,同1個(gè)QQ號(hào)碼就只能登錄1次,而不可能出現(xiàn)1個(gè)號(hào)碼可以登錄兩次的情況;再好像我現(xiàn)在聽歌用的播放器,我也只能打開它1次,當(dāng)它在運(yùn)行的時(shí)候,我不能夠同時(shí)運(yùn)行兩個(gè)播放器客戶端。。。等等的這些模式都是單例的,即它能保證1個(gè)類就只有1個(gè)實(shí)例對(duì)象。
這里應(yīng)用書中的例子去解釋構(gòu)造單例的方法。
1個(gè)國家需要有1個(gè)皇帝,并且這個(gè)皇帝就只能有1個(gè),那末,很明顯,它是單例的。我們需要構(gòu)造1個(gè)皇帝類,且這個(gè)皇帝類只能有1個(gè)實(shí)例對(duì)象,那末,這里就會(huì)出現(xiàn)1個(gè)限制,即這個(gè)類的構(gòu)造方法需要是私有的(private),否則,我們可以任意的生成對(duì)象。且這個(gè)類需要有1個(gè)靜態(tài)方法(static),當(dāng)我們需要這個(gè)類的對(duì)象時(shí),就能夠利用這個(gè)方法去獲得類對(duì)象。
好吧,看下具體的實(shí)現(xiàn)吧:
public class __Q_Y_Emperor {
/*這樣設(shè)計(jì)可以保證它是線程安全的*/
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...");
}
}
這個(gè)類的實(shí)現(xiàn)就是利用到單例模式,固然,這里只是單例模式的1種實(shí)現(xiàn)方式。
我們需要1個(gè)測(cè)試函數(shù),測(cè)試下這個(gè)單例模式是不是好用,這里,場(chǎng)景是有幾個(gè)大臣找皇帝,然后,每個(gè)大臣找到的都是同1個(gè)皇帝。
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)
{
/*獲得的實(shí)例對(duì)象都是同1個(gè)*/
__Q_Y_Emperor _Emperor = __Q_Y_Emperor.__Q_Y_GetInstance();
_Emperor.__Q_Y_Talk();
}
}
}
我們運(yùn)行下這個(gè)主函數(shù),得到以下的結(jié)果:
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
下面,看下類圖是怎樣的,很簡(jiǎn)單,沒有繼承關(guān)系之類的
書中從單例模式又引伸出了1個(gè)叫 “多例模式” 的設(shè)計(jì)方法,即1個(gè)類能產(chǎn)生多個(gè)對(duì)象,但是對(duì)象的個(gè)數(shù)是有限制的。 也一樣是皇帝的例子,只是這個(gè)例子中出現(xiàn)了多個(gè)皇帝,每一個(gè)大臣可能找到的是不同的皇帝。
好吧,這個(gè)也是很容易實(shí)現(xiàn)的:
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
{
/*多例模式,對(duì)象個(gè)數(shù)是有限制的*/
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));
}
}
測(cè)試函數(shù):
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();
}
}
}
類圖:
最后,運(yùn)行下這個(gè)例子吧:
num 3
num 2
num 2
num 2
num 3
num 1
num 2
num 2
num 1
num 1
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)