單例模式是一種常見的設計模式,在網上有許多,一找一大把,我今天看了,所以collection一下:
單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。
單例模式有一下特點:
1、單例類只能有一個實例。
2、單例類必須自己自己創建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
一、懶漢式單例
在類被加載的時候,唯一實例已經被創建。這個設計模式在Java中容易實現,在別的語言中難以實現。
/**
*懶漢式單例
*/
public class LazySingleton {
/**
* 私有靜態對象,加載時候不做初始化
*/
private static LazySingleton m_intance=null;
/**
* 私有構造方法,避免外部創建實例
*/
private LazySingleton(){
}
/**
* 靜態工廠方法,返回此類的唯一實例.
* 當發現實例沒有初始化的時候,才初始化.
* @return LazySingleton
*/
synchronized public static LazySingleton getInstance(){
if(m_intance==null){
m_intance=new LazySingleton();
}
return m_intance;
}
}
二、餓漢式單例
在類加載的時候不創建單例實例。只有在第一次請求實例的時候的時候創建,並且只在第一次創建後,以後不再創建該類的實例。
/**
*單例模式-餓漢式單例
*/
public class EagerSingleton {
/**
* 私有的(private)唯一(static final)實例成員,在類加載的時候就創建好了單例對象
*/
private static final EagerSingleton m_instance = new EagerSingleton();
/**
* 私有構造方法,避免外部創建實例
*/
private EagerSingleton() {
}
/**
* 靜態工廠方法,返回此類的唯一實例.
* @return EagerSingleton
*/
public static EagerSingleton getInstance() {
return m_instance;
}
}
三、登記式單例
這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。
/**
* 單例模式- 登記式單例
*/
public class RegSingleton {
/**
* 登記薄,用來存放所有登記的實例
*/
private static Map<String, RegSingleton> m_registry = new HashMap();
//在類加載的時候添加一個實例到登記薄
static {
RegSingleton x = new RegSingleton();
m_registry.put(x.getClass().getName(), x);
}
/**
* 受保護的默認構造方法
*/
protected RegSingleton() {
}
/**
* 靜態工廠方法,返回指定登記對象的唯一實例;
* 對於已登記的直接取出返回,對於還未登記的,先登記,然後取出返回
* @param name
* @return RegSingleton
*/
public static RegSingleton getInstance(String name) {
if (name == null) {
name = "RegSingleton";
}
if (m_registry.get(name) == null) {
try {
m_registry.put(name, (RegSingleton) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return m_registry.get(name);
}
/**
* 一個示意性的商業方法
* @return String
*/
public String about() {
return "Hello,I am RegSingleton!";
}
}
四、單例模式的一個應用
該應用是配置文件管理類。爲了本例能正確運行,我在C盤下先建立了一個xxxx.properties文件,內容如下:
-------------------
user=root
password=root
這個配置文件管理類的代碼如下:
/**
*
* 單例模式應用-單例類應用-配置文件管理
*/
public class ConfigManager {
/**
* 屬性文件全名
*/
private static final String PFILE = "C://xxx.properties";
/**
* 對應於屬性文件的文件對象變量
*/
private File m_file = null;
/**
* 屬性文件的最後修改日期
*/
private long m_lastModifiedTime = 0;
/**
* 屬性文件所對應的屬性對象變量
*/
private Properties m_props = null;
/**
* 本類可能存在的唯一的一個實例
*/
private static ConfigManager m_instance = new ConfigManager();
/**
* 私有構造子,用以保證外界無法直接實例化
*/
private ConfigManager() {
m_file = new File(PFILE);
m_lastModifiedTime = m_file.lastModified();
if (m_lastModifiedTime == 0) {
System.err.println(PFILE + " file does not exist!");
}
m_props = new Properties();
try {
m_props.load(new FileInputStream(PFILE));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 靜態工廠方法
*
* @return ConfigManager
*/
synchronized public static ConfigManager getInstance() {
return m_instance;
}
/**
* 獲取屬性配置項的值
*
* @param name
* @param defaultVal
* @return Object
*/
public final Object getConfigItem(String name, Object defaultVal) {
long newTime = m_file.lastModified();
if (newTime == 0) {
//屬性文件不存在
if (m_lastModifiedTime == 0) {
System.err.println(PFILE + " file does not exist!");
} else {
System.err.println(PFILE + " file was deleted!");
}
return defaultVal;
} else if (newTime > m_lastModifiedTime) {
m_props.clear();
try {
m_props.load(new FileInputStream(PFILE));
} catch (IOException e) {
e.printStackTrace();
}
}
m_lastModifiedTime = newTime;
Object val = m_props.getProperty(name);
if (val == null) {
return defaultVal;
} else {
return val;
}
}
}
測試配置文件類:
/**
*
* 配置文件管理類測試
*/
public class Test_ConfigManager {
public static void main(String[] args) {
ConfigManager cfgm = ConfigManager.getInstance();
Object val1 = cfgm.getConfigItem("sdf", "leizhimin");
Object val2 = cfgm.getConfigItem("user", "leizhimin");
System.out.println(val1.toString());
System.out.println(val2.toString());
}
}
運行結果:
root
root
Process finished with exit code 0