從最初的狀態 一步一步重構出dao模式

http://www.mldn.cn/articleview/2008-6-23/article_view_3195.htm 

 

一、前言
    本文的目的是將一個獲取數據庫連接的普通類重構成DAO+Abstract Factory模式。
    二、設計初衷
    使用數據訪問對象(DAO,Data Access Object)模式來抽象和封裝所有對數據源的訪問。DAO管理着與數據源的連接以便檢索和存儲數據。可以降低商業邏輯層和數據訪問層的耦合度,提高應用的可維護性和可移植性。
    由於底層數據源實現變化時,DAO向客戶端提供的接口不會變化,所有該模式允許DAO調整到不同的存儲模式,而不會影響其客戶端或者業務組件。顯然,DAO充當了組件和數據源之間的適配器。
    三、重構
    首先,創建一個獲取數據庫連接的普通類:
    DAOClient.java
    import java.sql.*;
    publicclass DAOClient {
        publicstaticvoid main( String[] args ) {
           try {
               //For Oracle
               Class.forName( "oracle.jdbc.driver.OracleDriver" );
               Connection conn = DriverManager.getConnection(
                      "jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
               System.out.println( conn.toString() );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
        }
    }

    再將這段代碼封裝到一個getConnection()方法中以便其它的地方調用:
    import java.sql.*;
    publicclass DAOClient {
        publicstaticvoid main( String[] args ) {
           Connection conn = getConnection();
           System.out.println( conn.toString() );
        }
        /**
         *得到一個Connection對象
         *@returnjava.sql.Connection
         */
        privatestatic Connection getConnection() {
           Connection conn = null;
           try {
               //For Oracle
               Class.forName( "oracle.jdbc.driver.OracleDriver" );
               conn = DriverManager.getConnection(
                      "jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
           return conn;
        }
    }

    再將此方法定義到針對Oracle的工廠類中:
    OracleDAOFactory.java
    import java.sql.*;
    publicclass OracleDAOFactory {
        private OracleDAOFactory() {}
        /**
         *返回一個OracleDAOFactory對象
         *@returnOracleDAOFactory類型對象
         */
        publicstatic OracleDAOFactory newInstance() {
           returnnew OracleDAOFactory();
        }
        /**
         *得到一個Connection對象
         *@returnjava.sql.Connection
         */
        public Connection getConnection() {
           Connection conn = null;
           try {
               //For Oracle
               Class.forName( "oracle.jdbc.driver.OracleDriver" );
               conn = DriverManager.getConnection(
                      "jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
           return conn;
        }
    }

    此時,DAOClient.java這個測試類的代碼應修改爲:
    import java.sql.*;
    public class DAOClient {
        publicstaticvoid main( String[] args ) {
           Connection conn = OracleDAOFactory.newInstance().getConnection();
           System.out.println( conn.toString() );
        }
    }

    考慮:通常,數據庫服務器、數據庫名、數據庫用戶、密碼等應該從配置文件中獲取。因此,修改Oracle的工廠類:
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    publicclass OracleDAOFactory {
        privatestatic Properties prop = new Properties();
        static {
           try {
               prop.load( OracleDAOFactory.class
                      .getResourceAsStream( "config.properties" ) );
           } catch ( IOException e ) {
               System.out.println( "File:config.properties no find,PLS check out!" );
               e.printStackTrace();
           }
        }
        private String CONNECTION_SERVER_NAME = prop
               .getProperty( "oracle_server_name" );
        private String CONNECTION_DRIVER = prop.getProperty( "oracle_conn_driver" );
        private String CONNECTION_DBINSTANCE = prop
               .getProperty( "oracle_dbInstance" );
        private String CONNECTION_USER = prop.getProperty( "oracle_conn_user" );
        private String CONNECTION_PWD = prop.getProperty( "oracle_conn_pwd" );
        private String CONNECTION_URL = "jdbc:oracle:thin:@"
               + CONNECTION_SERVER_NAME + ":1521:" + CONNECTION_DBINSTANCE;

       private OracleDAOFactory() {}
        /**
         *返回一個OracleDAOFactory對象
         *@returnOracleDAOFactory類型對象
         */
        publicstatic OracleDAOFactory newInstance() {
           returnnew OracleDAOFactory();
        }
        /**
         *得到一個Connection對象
         *@returnjava.sql.Connection
         */
        public Connection getConnection() {
           Connection conn = null;
           try {
               Class.forName( CONNECTION_DRIVER );
               conn = DriverManager.getConnection(
                      CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
           return conn;
        }
    }

    添加配置文件config.properties:
    oracle_server_name=localhost
    oracle_conn_driver=oracle.jdbc.driver.OracleDriver
    oracle_dbInstance=dy
    oracle_conn_user=scott
    oracle_conn_pwd=tiger

    繼續考慮,客戶端在獲取數據庫連接時使用的是針對Oracle的數據庫的工廠,但如果數據庫變化了,那麼客戶端的代碼還是要改變。因此,可以定義一個DAOFactory類,定義了一個抽象方法:getConnection()用於獲取數據庫連接,還有一個getDAOFactory()方法,根據參數dbType的值,返回不同的DAOFactory。
    DAOFactory.java
    import java.sql.Connection;
    publicabstractclass DAOFactory {
        publicstaticfinalintORACLE = 1;
        publicstaticfinalintSQLSERVER = 2;
        publicstaticfinalintMYSQL = 3;

        public abstract Connection getConnection();

        publicstatic DAOFactory getDAOFactory( int dbType ) {
           switch( dbType ) {
           caseORACLE:
               return OracleDAOFactory.newInstance();
           caseSQLSERVER:
               return SqlDAOFactory.newInstance();
           caseMYSQL:
               return MySqlDAOFactory.newInstance();
           default:
               returnnull;
           }
        }
    }

    SqlDAOFactory.java
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    publicclass SqlDAOFactory extends DAOFactory {
        privatestatic Properties prop = new Properties();
        static {
           try {
               prop.load( OracleDAOFactory.class
                      .getResourceAsStream( "config.properties" ) );
           } catch ( IOException e ) {
               System.out.println( "File:config.properties no find,PLS check out!" );
               e.printStackTrace();
           }
        }
        private String CONNECTION_SERVER_NAME = prop
               .getProperty( "sqlserver_server_name" );
        private String CONNECTION_DRIVER = prop.getProperty( "sqlserver_conn_driver" );
        private String CONNECTION_DBINSTANCE = prop
               .getProperty( "sqlserver_dbInstance" );
        private String CONNECTION_USER = prop.getProperty( "sqlserver_conn_user" );
        private String CONNECTION_PWD = prop.getProperty( "sqlserver_conn_pwd" );
        private String CONNECTION_URL = "jdbc:microsoft:sqlserver://"
               + CONNECTION_SERVER_NAME + ":1433;DatabaseName="
               + CONNECTION_DBINSTANCE;

        private SqlDAOFactory() {}
        /**
         *返回一個SqlDAOFactory對象
         *@returnSqlDAOFactory類型對象
         */
        publicstatic SqlDAOFactory newInstance() {
           returnnew SqlDAOFactory();
        }
        /**
         *得到一個Connection對象
         *@returnjava.sql.Connection
         */
        public Connection getConnection() {
           Connection conn = null;
           try {
               Class.forName( CONNECTION_DRIVER );
               conn = DriverManager.getConnection(
                      CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
           return conn;
        }
    }

    MySqlDAPFactory.java
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    publicclass MySqlDAOFactory extends DAOFactory {
        privatestatic Properties prop = new Properties();
        static {
           try {
               prop.load( OracleDAOFactory.class
                      .getResourceAsStream( "config.properties" ) );
           } catch ( IOException e ) {
               System.out.println( "File:config.properties no find,PLS check out!" );
               e.printStackTrace();
           }
        }
        private String CONNECTION_SERVER_NAME = prop
               .getProperty( "mysql_server_name" );
        private String CONNECTION_DRIVER = prop.getProperty( "mysql_conn_driver" );
        private String CONNECTION_DBINSTANCE = prop
               .getProperty( "mysql_dbInstance" );
        private String CONNECTION_USER = prop.getProperty( "mysql_conn_user" );
        private String CONNECTION_PWD = prop.getProperty( "mysql_conn_pwd" );
        private String CONNECTION_URL = "jdbc:mysql://"
               + CONNECTION_SERVER_NAME + ":3306/" + CONNECTION_DBINSTANCE
               + "?useUnicode=true&characterEncoding=UTF-8";

        private MySqlDAOFactory() {}
        /**
         *返回一個MySqlDAOFactory對象
         *@returnMySqlDAOFactory類型對象
         */
        publicstatic MySqlDAOFactory newInstance() {
           returnnew MySqlDAOFactory();
        }
        /**
         *得到一個Connection對象
         *@returnjava.sql.Connection
         */

       public Connection getConnection() {
           Connection conn = null;
           try {
               Class.forName( CONNECTION_DRIVER );
               conn = DriverManager.getConnection(
                      CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
           } catch ( ClassNotFoundException e ) {
               e.printStackTrace();
           } catch ( SQLException e ) {
               e.printStackTrace();
           }
           return conn;
        }
    }

    修改config.properties配置文件:
    #Oracle
    oracle_server_name=localhost
    oracle_conn_driver=oracle.jdbc.driver.OracleDriver
    oracle_dbInstance=dy
    oracle_conn_user=scott
    oracle_conn_pwd=tiger

    #SqlServer
    sqlserver_server_name=localhost
    sqlserver_conn_driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
    sqlserver_dbInstance=test
    sqlserver_conn_user=sa
    sqlserver_conn_pwd=sa

    #MySql
    mysql_server_name=localhost
    mysql_conn_driver=com.mysql.jdbc.Driver
    mysql_dbInstance=test
    mysql_conn_user=root
    mysql_conn_pwd=root

    最後,修改客戶端文件DAOClient.java代碼:
    import java.sql.*;
    public class DAOClient {
        public static void main( String[] args ) {
           DAOFactory dao = DAOFactory.getDAOFactory( DAOFactory.ORACLE );
           Connection conn = dao.getConnection();
           System.out.println( conn.toString() );
        }
    }

    通過這種DAO+(Abstract)Factory方式,在將程序遷移到其它數據庫中時,在客戶端程序中幾乎不用做修改,唯一需要做的,就是在獲得DAOFactory對象的時候,修改相應的參數,例如,遷移到MySql下的時候:
    DAOFactory dao = DAOFactory.getDAOFactory( DAOFactory.MYSQL );

發佈了35 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章