確保執行期應用程式中,某個類別**僅被實例化一次**,提供全域唯一存取點。Web 應用的核心分發 Servlet 即典型應用場景。
public class Singleton {
private Singleton() {} // 私有建構子
private static final Singleton instance = new Singleton(); // 靜態常量持有實例
public static Singleton getInstance() {
return instance; // 直接返回
}
}
優點:簡單、線程安全(類載入機制保證)、無同步開銷。
缺點:類載入即佔用記憶體,若未使用造成浪費。
public class Singleton {
private static volatile Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) { // 第一次檢查
synchronized (Singleton.class) {
if (instance == null) { // 第二次檢查
instance = new Singleton();
}
}
}
return instance;
}
}
優點:首次使用才建立,節省記憶體。
關鍵:volatile 禁止指令重排序,雙重檢查避免多執行緒重複建立。
public class DBManager {
private static final Logger logger = Logger.getLogger(DBManager.class);
private static DataSource dataSource;
// 餓漢式單例
private static final DBManager dbConManager = new DBManager();
private DBManager() {}
public void setDataSource(DataSource ds) {
if (dataSource == null) dataSource = ds;
}
public static DBManager getInstance() {
logger.info("獲取資料庫連線管理器實例");
return dbConManager;
}
public Connection getConnection() throws SQLException {
Connection conn = null;
try {
logger.info("從連線池獲取閒置連線");
conn = dataSource.getConnection();
return conn;
} catch (SQLException ex) {
logger.error("獲取連線失敗: " + ex.getMessage());
throw ex;
}
}
public void closeAll(Connection conn, Statement st, PreparedStatement pst,
CallableStatement cst, ResultSet rs) throws DBManagerException {
try {
if (rs != null) rs.close();
if (st != null) st.close();
if (pst != null) pst.close();
if (cst != null) cst.close();
if (conn != null) conn.close();
} catch (SQLException e) {
throw new DBManagerException("資料庫物件關閉出錯: " + e.getMessage(), e);
}
}
}
設計亮點:
✅ 單例封裝連線池存取邏輯
✅ 統一異常處理與日誌記錄
✅ closeAll 簡化資源釋放,避免重複樣板碼
✅ Struts 啟動時注入 DataSource,解耦框架依賴
volatile 與雙重檢查)。instance != null 拋異常,實作 readResolve() 返回現有實例。