為什么需要使用單例模式 屬性是系統的一種"資源",應當避免有多余一個的對象讀取非凡是存儲屬性。此外,屬性的讀取可能會在很多地方發生,創建屬性對象的地方應當在哪里不是很清楚。換言之,屬性治理器應當自己創建自己的實例,并且自己向系統全程提供這一事例。因此,屬性文件治理器應當是一個單例模式負責。
系統設計 系統的核心是一個屬性治理器,也就是一個叫做ConfigManager 的類,這個類應當是一個單例類。因此,這個類應當有一個靜態工廠方法,不妨叫做getInstance(), 用于提供自己的實例。
為簡單起見,本文在這里采取"餓漢"方式實現ConfigManager 。例子的類圖如下所示。

本例子的源代碼如下所示。
代碼清單6:ConfigManager 的源代碼
import java.util.Properties;
import java.io.FileInputStream;
import java.io.File;
public class ConfigManager
{
/**
* 屬性文件全名
*/
private static final String PFILE =
System.getProperty("user.dir")
+ File.Separator + "Singleton.properties";
/**
* 對應于屬性文件的文件對象變量
*/
private File m_file = null;
/**
* 屬性文件的最后修改日期
*/
private long m_lastModifiedTime = 0;
/**
* 屬性文件所對應的屬性對象變量
*/
private Properties m_props = null;
/**
* 本類可能存在的惟一的一個實例
*/
private static ConfigManager m_instance =
·234·Java 與模式
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(Exception e)
{
e.printStackTrace();
}
}
/**
* 靜態工廠方法
* @return 返還ConfigManager 類的單一實例
*/
synchronized public static ConfigManager
getInstance()
{
return m_instance;
}
/**
* 讀取一特定的屬性項
*
* @param name 屬性項的項名
* @param defaultVal 屬性項的默認值
* @return 屬性項的值(如此項存在), 默認值(如此項不存在)
*/
final public 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)
{
// Get rid of the old properties
m_props.clear();
try
{
m_props.load(new FileInputStream(PFILE));
}
catch(Exception e)
{
e.printStackTrace();
}
}
m_lastModifiedTime = newTime;
Object val = m_props.getProperty(name);
if( val == null )
{
return defaultVal;
}
else
{
return val;
}
}
}
在上面直接使用了一個局域的常量儲存儲屬性文件的路徑。在實際的系統中,讀者可以采取更靈活的方式將屬性文件的路徑傳入。
讀者可以看到,這個治理器類有一個很有意思的功能,即在每一次調用時,檢查屬性文件是否已經被更新過。假如確實已經被更新過的話,治理器會自動重新加載屬性文件, 從而保證治理器的內容與屬性文件的內容總是一致的。
怎樣調用屬性治理器 下面的源代碼演示了怎樣調用ConfigManager 來讀取屬性文件。
代碼清單7:怎樣調用ConfigManager 類以讀取屬性文件