單例模式就是確保一個類只有一個實例,并且該實例必須自動創建,并向整個系統提供該實例。這樣保證了對外的對象的屬性等均為一個實例,就像是銀行取款
單例模式原理圖:

單例模式分為餓漢式單例模式和懶漢式單例模式。
餓漢式單例模式代碼
~~~
package com.designpattern.singleton;
public class HungrySingleton {
private HungrySingleton() {
}
private static HungrySingleton instance = new HungrySingleton();
public static HungrySingleton getInstance() {
return instance;
}
}
~~~
懶漢式單例模式代碼
~~~
package com.designpattern.singleton;
public class LazySingleton {
private LazySingleton() {
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
~~~
事例中對于餓漢式是不管外部有沒有調用都new出了一個對象,二懶漢式只有在外部調用的時候,并且是第一次的時候才new出來對象的,但是一定要放在sychronized下面
這樣感覺像是懶漢模式是在調用的時候分配空間初始化instance的,但是自己感覺上面兩種是一樣的效果
在實例化先后順尋的角度分析:餓漢式類內static 對象會在構造器調用前初始化,也就是最先初始化,但是只初始化一次就不再初始化了,畢竟是static的,在構造器之前也就是只有在使用這個類的時候,才實例化。同時后者懶漢式中私有的static也會在構造器之前初始化,但是是null,這樣就在第一次調用這個類的時候對instance進行了初始化,但是之后就不會再初始化了,原因也是static,這樣看起來對于懶漢和餓漢的初始化和構造過程是一樣的。
不過說道具體的地方餓漢式是在加載類的時候創建對象,而懶漢式是在調用getInstance時候創建對象,那么這樣他們在創建的時候還是用一定的區別的。
下面借著這個Singleton模式簡單的做了一個Log工具,實現對于一個日志工具不會多次初始化,并且不會覆蓋掉而是尾加,Log4j就是一個Singleton的實例
~~~
package com.designpattern.singleton;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Log {
private static final String DefalutLogFilePathName = System
.getProperty("user.dir")
+ File.separator + "user.log";
private static Log log;
private static PrintWriter pw;
private Log() {
pwinit();
}
public static synchronized void log(String message) {
if (log == null || pw == null) {
log = new Log();
}
if (pw != null) {
pw.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date())
+ " : " + message);
}
}
public static void destroy() {
log = null;
if (pw != null) {
pw.close();
}
}
private void pwinit() {
if (pw == null) {
try {
pw = new PrintWriter(new FileWriter(DefalutLogFilePathName,
true), true);
} catch (IOException e) {
e.printStackTrace();
pw = null;
}
}
}
}
~~~
在Client端對Log進行操作,不會覆蓋結果,測試成功
~~~
package com.designpattern.singleton;
public class Client {
public static void main(String[] args) {
System.out.print("Log");
System.out.print("\t");
Log.log("start");
Log.log("middle");
Log.log("end");
Log.destroy();
}
}
~~~
輸出結果:
~~~
2012-04-05 14:46:15 : start
2012-04-05 14:46:15 : middle
2012-04-05 14:46:15 : end
~~~
在單例模式中,客戶調用類的實例時,只能調用一個公共接口,這就是為整個開發團隊提供了共享的概念。
但是但是模式的類在實例化以后,不能被別的類繼承,在分布式系統中,當系統中的單例類被復制運行在多個虛擬機下時,在每一個虛擬機下都會創建一個實例對象,此時如果想知道具體那個虛擬機下運行著哪個單例對象是很困難的,而且單例類很難實現序列化。
- 前言
- 前言(目錄、源碼、資料)
- (一)簡單工廠模式(SimpleFatory)
- (二)工廠方法模式(FactoryMethod)
- (三)抽象工廠模式(AbstractFactory)
- (四)創建者模式(Builder)
- (五)原型模式(Prototype)
- (六)單例模式(Singleton)
- (七)外觀模式(Facade)
- (八)適配器模式(Adapter)
- (九)代理模式(Proxy)
- (十)裝飾模式(Decorator)
- (十一)橋模式(birdge)
- (十二)組合模式(Composite)
- (十三)享元模式(Flyweight)
- (十四)模板方法模式(Template)
- (十五)觀察者模式(Observer)
- (十六)狀態模式(State)