java 單例模式的好處

來源:互聯網
上載者:User

 

單例模式是一種常見的設計模式,在《Java與模式》一書中,閻宏博士對單例模式做了全面的總結。

單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。

單例模式有一下特點:

1、單例類只能有一個執行個體。

2、單例類必須自己建立自己的唯一執行個體。

3、單例類必須給所有其他對象提供這一執行個體。

說明:一下的代碼來自閻宏博士的《Java與模式》一書,其中對一些類的寫法做調整(符合Java1.5的習慣),另外還加了測試方法。

一、懶漢式單例

在類被載入的時候,唯一執行個體已經被建立。這個設計模式在Java中容易實現,在別的語言中難以實現。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 14:57:08

* <> 單例模式-懶漢式單例

*/

public class LazySingleton {

     /**

      * 私人靜態對象,載入時候不做初始化

      */

     private static LazySingleton m_intance=null;

     /**

      * 私人構造方法,避免外部建立執行個體

      */

     private LazySingleton(){

     }

     /**

      * 靜態Factory 方法,返回此類的唯一執行個體. 

      * 當發現執行個體沒有初始化的時候,才初始化.

      * @return LazySingleton

      */

     synchronized public static LazySingleton getInstance(){

         if(m_intance==null){

             m_intance=new LazySingleton();

         }

         return m_intance;

     }

}

二、餓漢式單例

在類載入的時候不建立單例執行個體。只有在第一次請求執行個體的時候的時候建立,並且只在第一次建立後,以後不再建立該類的執行個體。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 14:45:25

* <> 單例模式-餓漢式單例

*/

public class EagerSingleton {

     /**

      * 私人的(private)唯一(static final)執行個體成員,在類載入的時候就建立好了單例對象

      */

     private static final EagerSingleton m_instance = new EagerSingleton();

     /**

      * 私人構造方法,避免外部建立執行個體

      */

     private EagerSingleton() {

     }

     /**

      * 靜態Factory 方法,返回此類的唯一執行個體.

      * @return EagerSingleton

      */

     public static EagerSingleton getInstance() {

         return m_instance;

     }

}

三、登記式單例

這個單例實際上維護的是一組單例類的執行個體,將這些執行個體存放在一個Map(登記薄)中,對於已經登記過的執行個體,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 15:20:16

* <> 單例模式- 登記式單例

*/

public class RegSingleton {

     /**

      * 登記薄,用來存放所有登記的執行個體

      */

     private static Map m_registry = new HashMap();

     //在類載入的時候添加一個執行個體到登記薄

     static {

         RegSingleton x = new RegSingleton();

         m_registry.put(x.getClass().getName(), x);

     }

     /**

      * 受保護的預設構造方法

      */

     protected RegSingleton() {

     }

     /**

      * 靜態Factory 方法,返回指定登錄物件的唯一執行個體;

      * 對於已登記的直接取出返回,對於還未登記的,先登記,然後取出返回

      * @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=leizhimin

這個設定檔管理類的代碼如下:

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 15:55:01

* 單例模式應用-單例類應用-設定檔管理

*/

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();

         }

     }

     /**

      * 靜態Factory 方法

      *

      * @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;

         }

     }

}

測試組態檔案類:

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 16:42:45

* 設定檔管理類測試

*/

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());

     }

}

運行結果:

leizhimin

root

Process finished with exit code 0

五、筆者寫的一個JDBC資料庫工具類的單例實現

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 18:04:46

* 單例模式在JDBC編程中的應用,用於設計資料庫工具類

*/

public class DBUtil {

     //單一執行個體

     private static final DBUtil _instance = new DBUtil();

     //資料來源的JNDI

     private static final String datasource = "java:comp/env/jdbc/zvfims";

     /**

      * 私人構造方法,防止外部執行個體化

      */

     private DBUtil() {

     }

     /**

      * 資料庫工具類執行個體工廠

      *

      * @return DBUtil

      */

     public DBUtil getInstance() {

         return _instance;

     }

     /**

      * 業務方法:用於擷取資料庫連接

      *

      * @return Connection

      */

     public Connection makeConnection() {

         Connection conn = null;

         try {

             Context ctx = new InitialContext();

             DataSource ds = (DataSource) ctx.lookup(datasource);

             conn = ds.getConnection();

         } catch (NamingException e) {

             System.out.println("擷取資料來源異常,請AppServer的JNDI資料來源配置!");

             e.printStackTrace();

         } catch (SQLException e) {

             System.err.println("擷取資料庫連接發生異常!");

             e.printStackTrace();

         }

         return conn;

     }

}

通過這個單例類和開放的業務方法,可以為整個系統應用提供資料庫連接。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.