單例設(shè)計(jì)模式基本上是用來(lái)控制創(chuàng)建許多對(duì)象,因此屬于家庭創(chuàng)建模式。
早期的趨勢(shì)是創(chuàng)建一個(gè)馬克斯的對(duì)象,但在某些情況下,我們需要一個(gè)固定數(shù)量的對(duì)象; 這種模式是正確的,來(lái)幫助我們。 通常,我們構(gòu)造函數(shù)標(biāo)記為私有,以確保外部世界不能創(chuàng)建對(duì)象,提供了一個(gè)靜態(tài)方法,簡(jiǎn)單地返回對(duì)象。 它創(chuàng)建一個(gè)物體只有在沒(méi)有事先創(chuàng)建。
隨著時(shí)間的推移,人們意識(shí)到這種香草的實(shí)現(xiàn)單例,幾個(gè)問(wèn)題,這是改善來(lái)解決這些問(wèn)題。 注意,單件不對(duì)錯(cuò); 只要適合你的問(wèn)題域。
在這次演講中,我們將看看不同實(shí)現(xiàn)的單例。
讓我們看看類(lèi)圖:

單使用
有幾個(gè)地方是明智的使用單例模式。 例如:日志記錄、緩存、負(fù)載平衡、配置、通信(IO避免表現(xiàn)不佳或遠(yuǎn)程)和數(shù)據(jù)庫(kù)連接池。 單例的Java API的一個(gè)例子是運(yùn)行時(shí)類(lèi)。
單例實(shí)現(xiàn)
這是香草的方式使用一個(gè)立即加載機(jī)制,實(shí)現(xiàn)一個(gè)單例是線(xiàn)程安全的。
public class MySingleton {
private static final MySingleton mySingleton = new MySingleton();
private MySingleton(){}
public static MySingleton getInstance(){
return mySingleton;
}
}
另一方面,這里有一個(gè)例子使用延遲加載機(jī)制實(shí)現(xiàn)單例。 在多線(xiàn)程應(yīng)用程序中,這將是一個(gè)糟糕的方法。
class MySingleton {
private static MySingleton mySingleton;
private MySingleton(){}
public static MySingleton getInstance(){
if(null == mySingleton) {
mySingleton = new MySingleton();
}
return mySingleton;
}
}
一個(gè)多線(xiàn)程的方法可以避免競(jìng)態(tài)條件,以確保它不會(huì)違反一個(gè)單例的哲學(xué)。 但是在下面的例子中,使整個(gè)方法“同步”并不是一個(gè)好方法,因?yàn)槲覀冃枰焰i對(duì)象創(chuàng)建語(yǔ)句。
class MySingleton {
private static MySingleton mySingleton;
private MySingleton(){}
public synchronized static MySingleton getInstance(){
if(null == mySingleton) {
mySingleton = new MySingleton();
}
return mySingleton;
}
}
下面的多線(xiàn)程的實(shí)現(xiàn)方式可以避免競(jìng)態(tài)條件,以確保它不會(huì)違反獨(dú)立的哲學(xué)和雙重檢查鎖定的幫助下使用對(duì)象級(jí)別的鎖會(huì)達(dá)到相同的。 這個(gè)實(shí)現(xiàn)保證線(xiàn)程安全; 但一直鎖所需的額外的對(duì)象是這不是一個(gè)很好的實(shí)踐。 另一個(gè)缺點(diǎn)是,有人可以使用類(lèi)級(jí)別鎖你的鎖的優(yōu)點(diǎn)是在一個(gè)不同的對(duì)象
class MySingleton {
private static MySingleton mySingleton;
private static final Object lock = new Object();
private MySingleton(){}
public static MySingleton getInstance(){
if(null == mySingleton) {
synchronized(lock) {
if(null == mySingleton) {
mySingleton = new MySingleton();
}
}
}
return mySingleton;
}
}
另一個(gè)multi-threaded-based實(shí)現(xiàn)(避免競(jìng)態(tài)條件)的幫助下可以實(shí)現(xiàn)雙重檢查鎖定使用類(lèi)級(jí)別鎖。 在這里,將MySingleton對(duì)象標(biāo)記為不穩(wěn)定將確保變化由一個(gè)線(xiàn)程應(yīng)該在另一個(gè)是可見(jiàn)的。 這個(gè)實(shí)現(xiàn)保證線(xiàn)程安全。
class MySingleton {
private volatile static MySingleton mySingleton;
private MySingleton() {}
public static MySingleton getInstance() {
if (null == mySingleton) {
synchronized(MySingleton.class) {
if (null == mySingleton) {
mySingleton = new MySingleton();
}
}
}
return mySingleton;
}
}
這意味著實(shí)現(xiàn)提供了一個(gè)聰明的構(gòu)造函數(shù),將停止單合同違反使用反射。
class MySingleton {
private volatile static MySingleton mySingleton;
//Reflection can't hack to create more than one object.
private MySingleton() throws Exception {
if (null == mySingleton) {
mySingleton = new MySingleton();
} else {
throw new Exception("It's a singleton class; don't expect more object to get produced");
}
}
public static MySingleton getInstance() throws Exception {
if (null == mySingleton) {
synchronized(MySingleton.class) {
if (null == mySingleton) {
mySingleton = new MySingleton();
}
}
}
return mySingleton;
}
}
這是一個(gè)非常受歡迎的實(shí)現(xiàn)使用一個(gè)靜態(tài)類(lèi),這帶來(lái)了延遲加載和線(xiàn)程安全的權(quán)力。
public class MySingleton {
private MySingleton() {}
private static class SingletonUisngInner {
private static MySingleton mySingleton = new MySingleton();
}
public static MySingleton getInstance() {
return SingletonUisngInner.mySingleton;
}
}
在某些情況下,如果你的單例類(lèi)繼承接口可克隆屬性,那么你的單例類(lèi)需要格外小心,防止單例設(shè)計(jì)合同。 你的單例類(lèi)應(yīng)該覆蓋的克隆方法和顯式地拋出CloneNotSupportedException。
class ClonedClass implements Cloneable {
//Some logic
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class MySingleton extends ClonedClass {
private MySingleton() {}
private static class SingletonUisngInner {
private static MySingleton mySingleton = new MySingleton();
}
public static OneMore getInstance() {
return singletonUisngInner.mySingleton;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
另一個(gè),我們的決賽,非常受歡迎的和智能的方法實(shí)現(xiàn)單例使用枚舉,而照顧我們到目前為止的所有問(wèn)題。
public enum EnumSingleton{
INSTANCE;
}
有時(shí),人們談?wù)搯渭缍鄠€(gè)jvm,讓我們觸摸。 單身意味著只有一個(gè)對(duì)象,我們非常清楚,JVM對(duì)象生命周期管理,所以一個(gè)共享對(duì)象跨多個(gè)JVM是不可能的。
但是如果你需要,你可以在一個(gè)JVM中創(chuàng)建對(duì)象并分發(fā)它作為一個(gè)序列化的對(duì)象,可以使用其他JVM(但是記住,你反序列化,那么請(qǐng)記住,任何靜態(tài)或標(biāo)記為瞬態(tài)將無(wú)法實(shí)現(xiàn),某個(gè)地方,打破了單合同)。 你也可以嘗試使用RMI服務(wù)器對(duì)象作為單件來(lái)適應(yīng)您的需要。
學(xué)習(xí)快樂(lè)!