Java设计模式之单例模式(singleton模式)

来源:互联网 发布:无标度网络应用 编辑:程序博客网 时间:2024/04/26 03:00

1. 概念:

 

    确保在一个JVM中一个类只有一个实例对象存在,这个类自已创建实例对象,并向整个系统提供此实例。

 

2. 单例实现:

 

    (1)饿汉式单例:


view plain
package com.focus;  
public class EagerSingleton {  
    /** 
     * 构造方法使用private修饰符修饰。 
     */  
    private EagerSingleton() {  
          
    }  
      
    public static EagerSingleton getInstance() {  
        return mEagerSingleton;  
    }  
    private static EagerSingleton mEagerSingleton = new EagerSingleton();  
          
}   

    (2)懒汉式单例:


view plain
package com.focus;  
public class LazySingleton {  
    /** 
     * 构造方法使用private修饰符修饰。 
     */  
    private LazySingleton() {  
          
    }  
      
    public static synchronized LazySingleton getInstance() {  
        if (mSingletonTwo == null) {  
            mSingletonTwo = new LazySingleton();  
        }  
          
        return mSingletonTwo;  
    }  
    private static LazySingleton mSingletonTwo = null;  
}  
 
    (3)登记式单例:
view plain
package com.focus;  
import java.util.HashMap;  
import java.util.Map;  
public class RegSingleton {  
    private static Map<String, RegSingleton> mRegSingletonMap = new HashMap<String, RegSingleton>();  
    static {  
        RegSingleton regSingleton = new RegSingleton();  
        mRegSingletonMap.put(regSingleton.getClass().getName(), regSingleton);  
    }  
    /** 
     * 构造方法用protected修饰符修饰。 
     */  
    protected RegSingleton() {  
          
    }  
    public static RegSingleton getInstance(String singletonThreeName) {  
        if (singletonThreeName == null) {  
            singletonThreeName = "RegSingleton";  
        }  
          
        if (mRegSingletonMap.get(singletonThreeName) == null) {  
            try {  
                mRegSingletonMap.put(singletonThreeName, (RegSingleton) Class.forName(singletonThreeName).newInstance());  
            } catch (InstantiationException e) {  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                e.printStackTrace();  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            }  
        }  
          
        return mRegSingletonMap.get(singletonThreeName);  
    }  
}  

 

3. 使用场景:

 

    (1)系统配置文件,只需要加载一次,为各个模块提供配置信息,可以用单例实现,代码如下:


view plain
package com.focus;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.util.Properties;  
public class PropertyReader {  
      
    private static final String FILE_PATH = "*.properties";     
      
    private Properties mProperties = null;      
          
    private static PropertyReader mPropertyReader = new PropertyReader();      
          
    private PropertyReader() {  
        File file = new File(FILE_PATH);  
          
        if (file.exists()) {  
             mProperties = new Properties();     
               
             try {              
                 mProperties.load(new FileInputStream(FILE_PATH));          
             } catch (IOException e) {             
                 e.printStackTrace();          
             }      
        }  
    }      
          
    public synchronized static PropertyReader getInstance() {          
        return mPropertyReader;      
    }      
      
    public final String getProperty(String key, String defaultValue) {  
        if (mProperties == null) {  
            throw new IllegalStateException();  
        }  
          
        return mProperties.getProperty(key, defaultValue);  
    }  
      
    /** 
     * 同步更新配置。 
     */  
    public final synchronized void setProperty(String key, String value) {  
        try {  
            mProperties.setProperty(key, value);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
      
}   

    (2)数据库连接池,为整个系统提供数据库连接,可以用单例实现:

 

                A. Pool类实现:


view plain
package com.focus;  
import java.sql.Connection;  
import java.sql.Driver;  
import java.sql.DriverManager;  
import java.sql.SQLException;  
public class Pool {  
      
    /** 
     * 单例模式(Singleton模式),构造方法为私有的。 
     */  
    private Pool() {  
        loadDriver(mDriverName);  
        createPool();  
    }  
    /** 
     * 装载和注册所有JDBC驱动程序。 
     */  
    private void loadDriver(String driverName) {  
        if (driverName != null && ! "".equals(driverName)) {  
            try {  
                mDriver = (Driver) Class.forName(driverName).newInstance();  
                DriverManager.registerDriver(mDriver);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    /** 
     * 创建连接池 
     */  
    private void createPool() {  
        mDBConnectionPool = new DBConnectionPool(mDatabasePassword, mDatabaseURL, mDatabaseUserName, mNormalConnectNum, mMaxConnectNum);  
        if (mDBConnectionPool != null) {  
            System.out.println("创建连接池成功!");  
        } else {  
            System.out.println("创建连接池失败!");  
        }  
    }  
    /** 
     * 获取单例实例。 
     */  
    public static synchronized Pool getInstance() {  
        if (mInstance == null) {  
            mInstance = new Pool();  
        }  
        return mInstance;  
    }  
    public Connection getConnection() {  
        if (mDBConnectionPool != null) {  
            return mDBConnectionPool.getConnection();  
        } else {  
            return null;  
        }  
    }  
    public Connection getConnection(long timeOut) {  
        if (mDBConnectionPool != null) {  
            return mDBConnectionPool.getConnection(timeOut);  
        }  
        return null;  
    }  
    public void releaseFreeConnection(Connection connection) {  
        if (mDBConnectionPool != null) {  
            mDBConnectionPool.releaseFreeConnection(connection);  
        }  
    }  
    /** 
     * 返回当前空闲连接数 
     */  
    public int getnum() {  
        return mDBConnectionPool.getFreeConnectionNum();  
    }  
    /** 
     * 返回当前连接数 
     */  
    public int getnumActive() {  
        return mDBConnectionPool.getCurrentConnectionNum();  
    }  
    /** 
     * 关闭所有连接,撤销驱动注册。 
     */  
    public synchronized void release() {  
        /** 
         * 关闭连接 
         */  
        mDBConnectionPool.release();  
          
        /** 
         * 撤销驱动 
         */  
        try {  
            DriverManager.deregisterDriver(mDriver);  
            System.out.println("撤销JDBC驱动程序 " + mDriver.getClass().getName());  
        } catch (SQLException e) {  
            System.out.println("无法撤销JDBC驱动程序的注册:" + mDriver.getClass().getName());  
        }  
    }  
    private static Pool mInstance = null; // 定义唯一实例  
    private int mMaxConnectNum = 100;// 最大连接数  
    private int mNormalConnectNum = 10;// 保持连接数  
    private String mDatabasePassword = "";// 密码  
    private String mDatabaseURL = "jdbc:mysql://localhost/shop";// 连接URL  
    private String mDatabaseUserName = "root";// 用户名  
    private String mDriverName = "com.mysql.jdbc.Driver";// 驱动类  
    private Driver mDriver = null;// 驱动变量  
    private DBConnectionPool mDBConnectionPool = null;// 连接池实例变量  
}   

 

                B.DatabaseConnectionPool类实现:


view plain
package com.focus;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.SQLException;  
import java.util.Date;  
import java.util.Enumeration;  
import java.util.Vector;  
public class DBConnectionPool {  
      
    public DBConnectionPool(String databasePassWord, String databaseURL, String databaseUserName, int normalConnectionNum, int maxConnectionNum) {  
        mDatabasePassWord = databasePassWord;  
        mDatabaseURL = databaseURL;  
        mDatabaseUserName = databaseUserName;  
        mMaxConnectionNum = maxConnectionNum;  
          
        /* 初始normalConnectionNum个连接 */  
        for (int i = 0; i < normalConnectionNum; i++) {  
            Connection connection = createConnection();  
            if (connection != null) {  
                mFreeConnections.addElement(connection);  
                mFreeConnectionNum++;  
            }  
        }  
    }  
    /* 创建一个新连接 */  
    private Connection createConnection() {  
        Connection connection = null;  
          
        try {  
            if (mDatabaseUserName == null) {  
                connection = DriverManager.getConnection(mDatabaseURL);  
            } else {  
                connection = DriverManager.getConnection(mDatabaseURL, mDatabaseUserName, mDatabasePassWord);  
            }  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
          
        return connection;  
    }  
    /* 释放不用的连接到连接池 */  
    public synchronized void releaseFreeConnection(Connection con) {  
        mFreeConnections.addElement(con);  
        mFreeConnectionNum++;  
        mCheckedOut--;  
        mCurrentConnectionNum--;  
        notifyAll();  
    }  
    /* 返回当前空闲连接数 */  
    public int getFreeConnectionNum() {  
        return mFreeConnectionNum;  
    }  
    /* 返回当前连接数 */  
    public int getCurrentConnectionNum() {  
        return mCurrentConnectionNum;  
    }  
    // 获取一个可用连接  
    public synchronized Connection getConnection() {  
        Connection connection = null;  
          
        if (mFreeConnections.size() > 0) {  
              
            mFreeConnectionNum--;  
              
            connection = (Connection) mFreeConnections.firstElement();  
              
            mFreeConnections.removeElementAt(0);  
              
            try {  
                if (connection.isClosed()) {  
                    System.out.println("从连接池删除一个无效连接!");  
                    connection = getConnection();  
                }  
            } catch (SQLException e) {  
                System.out.println("从连接池删除一个无效连接!");  
                connection = getConnection();  
            }  
        } else if (mMaxConnectionNum == 0 || mCheckedOut < mMaxConnectionNum) { /* 没有空闲连接且当前连接小于最大允许值, 最大值为0则不限制 */  
            connection = createConnection();  
        }  
          
        if (connection != null) { /* 当前连接数加1 */  
            mCheckedOut++;  
        }  
          
        mCurrentConnectionNum++;  
          
        return connection;  
    }  
    /* 获取一个连接, 并加上等待时间限制, 时间为毫秒 */  
    public synchronized Connection getConnection(long timeout) {  
        long startTime = new Date().getTime();  
          
        Connection connection;  
          
        while ((connection = getConnection()) == null) {  
            try {  
                wait(timeout);  
            } catch (InterruptedException e) {  
                  
            }  
            if ((new Date().getTime() - startTime) >= timeout) {  
                return null; /* 超时返回 */  
            }  
        }  
          
        return connection;  
    }  
    /* 关闭所有连接 */  
    public synchronized void release() {  
        Enumeration connections = mFreeConnections.elements();  
          
        while (connections.hasMoreElements()) {  
              
            Connection connection = (Connection) connections.nextElement();  
              
            try {  
                connection.close();  
                mFreeConnectionNum--;  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
          
        mFreeConnections.removeAllElements();  
        mCurrentConnectionNum = 0;  
    }  
    private Vector<Connection> mFreeConnections = new Vector<Connection>();  
      
    private int mCheckedOut;  
    private int mMaxConnectionNum;  
      
    private String mDatabasePassWord;  
    private String mDatabaseURL;  
    private String mDatabaseUserName;  
      
    private static int mFreeConnectionNum = 0;/* 空闲的连接数 */  
    private static int mCurrentConnectionNum = 0;/* 当前的连接数 */  
}