單例模式
作爲對象的創建模式,單例模式確保某一類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱爲單例類。單例類的一個重要特點是它的構造方法是私有的,且此類不能被繼承。它有如下幾種結構:
1、餓漢式
餓漢式單例類是當這個類被加載時就被實例化
- public class EagerSingleton {
- public static EagerSingleton eagerInstance = new EagerSingleton();
- private EagerSingleton() {
- }
- public static EagerSingleton getInstance() {
- return eagerInstance;
- }
- }
餓漢式單例類可以在Java語言裏實現,不易在C++內實現,因爲靜態初始化在C++裏沒有固定的順序,因而靜態的eagerInstance變量初始化與類的加載順序沒有保證,這更符合Java語言的特點。
2、懶漢式
與餓漢式單例類不同的是,懶漢式單例類在第一次被引用時纔將自己實例化。
- public class LazySingleton {
- private static LazySingleton lazyInstance = null;
- private LazySingleton() {
- }
- public synchronized static LazySingleton getInstance() {
- if (lazyInstance == null) {
- lazyInstance = new LazySingleton();
- }
- return lazyInstance;
- }
- }
上面給出懶漢式單例類實現裏對靜態方法使用了同步化,以適應多線程環境。
3、登記式
登記式單例類是爲了克服上面兩種單例類均不能被繼承的缺點而設計的,它的子類實例化的方式只能是懶漢式的。
- package com.wgy.javapatterns.singleton;
- import java.util.HashMap;
- import java.util.Map;
- public class RegSingleton {
- private static Map registry = new HashMap();
- static {
- RegSingleton regInstance = new RegSingleton();
- registry.put(regInstance.getClass().getName(), regInstance);
- }
- protected RegSingleton() {
- }
- public static RegSingleton getInstance(String name) {
- if (name == null) {
- name = "com.wgy.javapatterns.singleton.RegSingleton";
- }
- if (registry.get(name) == null) {
- try {
- registry.put(name, Class.forName(name).newInstance());
- } catch (Exception e) {
- System.out.println("Error happened!");
- }
- }
- return (RegSingleton) registry.get(name);
- }
- public String sayHi() {
- return "Hello, I am RegSingleton!";
- }
- }
它的子類RegSingletonChild需要父類的幫助才能實例化,示例代碼如下:
- package com.wgy.javapatterns.singleton;
- public class RegSingletonChild extends RegSingleton {
- public RegSingletonChild() {
- }
- public static RegSingletonChild getInstance() {
- return (RegSingletonChild) RegSingleton
- .getInstance("com.wgy.javapatterns.singleton.RegSingletonChild");
- }
- public String sayHi() {
- return "Hello, I am RegSingletonChild!";
- }
- }
本例中加入了getInstance()方法,好處是RegSingletonChild可以通過這個方法返回自己的實例,缺點是由於數據類型不同,無法在RegSingleton提供這樣一個方法。
登記式單例類的缺點:由於子類必須允許父類以構造方法產生實例,因此它的構造方法必須是公開的,這等於允許了以這種方式產生實例而不在父類的登記中;由於父類的實例必須存在纔可能有子類的實例,這在有些情況下是種浪費。