當(dāng)需要強(qiáng)制要求某個特定對象只能有單一實例時,可以使用Singleton或者M(jìn)onoState模式完成.
首先看下兩種模式的經(jīng)典實現(xiàn)代碼(代碼摘自網(wǎng)絡(luò)http://www.codethinked.com/the-monostate-pattern).
public class Singleton
{
private static Singleton instance;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
public String DataItem { get; set; }
}
public class Monostate
{
private static string dataItem;
public string DataItem
{
get { return dataItem; }
set { dataItem = value; }
}
public Monostate(){ }
}
對于Singleton模式,關(guān)注的是Structural Constraint,即只有一個實例. 該模式具有以下的優(yōu)勢:
- 跨平臺.使用合適的中間件,能夠把該模式擴(kuò)展為跨多個JVM.
- 適合于任何類,針對任意普通類,通過簡單的改造都可以成為Singleton的.
- 延遲創(chuàng)建.只有在第一次調(diào)用Instance來獲取該單一實例時,才會進(jìn)行實例的創(chuàng)建工作.
而對于該模式也有不少的抱怨, 最大的問題在于類創(chuàng)建方式的不透明性. 假設(shè)現(xiàn)在有一個Service類需要實現(xiàn)為Singleton的, 那么該Service的所有使用者都需要被通知到,要使用Instance方法(getter),而非new的方式來獲取該類的實例.
另一個較為嚴(yán)重的問題是可能的內(nèi)存泄露.如果在Singleton類中持有一些全局資源,那么是沒有合適的時機(jī)進(jìn)行資源釋放的.
MonoState模式部分解決了Singleton模式的缺陷,它關(guān)注的是Behaviour. 該模式具有以下的優(yōu)勢:
- 透明性.對于創(chuàng)建者而已,創(chuàng)建MonoState類的實例和創(chuàng)建普通類的實例是一致的(通過new()).這減少了溝通成本.
- 可派生性. MonoState的派生類也具有MonoState性的. 這主要是因為子類和父類共享相同的static數(shù)據(jù)域. MonoState的繼承, 可以看做是基于相同數(shù)據(jù)下的行為多態(tài)性的派生.
當(dāng)派生類也需要具有單實例特性時,MonoState模式的優(yōu)勢是巨大的,MonoState子類天生就是MonoState的.
當(dāng)然,MonoState模式也是有爭議的,最大的爭議當(dāng)屬static數(shù)據(jù)域的恰當(dāng)性. 全局static數(shù)據(jù),是導(dǎo)致不少程序Bug的源頭. 其次由于靜態(tài)數(shù)據(jù)是單個JVM作用域內(nèi)的,所以它是不可跨JVM的.
當(dāng)我們需要單實例特性時,如果知會使用者要使用Instance而非new來獲取實例不會造成麻煩,那么Singleton模式會是首選. 而當(dāng)需要保證MonoState是可繼承時,使用MonoState模式是不錯的選擇.