如何重构出DAO模式?

 
如何重构 DAO 模式
本文是在刘晓涛老师布置的课后作业,再由T10班级邓延课后总结而成。采取逐步重构的方法。版权有刘晓涛与邓延共有,转载需保留出处!
一、前言
本文的目的是将一个获取数据库连接的普通类重构成DAO+Abstract Factory模式。
二、设计初衷
使用数据访问对象(DAO,Data Access Object)模式来抽象和封装所有对数据源的访问。DAO管理着与数据源的连接以便检索和存储数据。可以降低商业逻辑层和数据访问层的耦合度,提高应用的可维护性和可移植性。
由于底层数据源实现变化时,DAO向客户端提供的接口不会变化,所有该模式允许DAO调整到不同的存储模式,而不会影响其客户端或者业务组件。显然,DAO充当了组件和数据源之间的适配器。
三、重构
首先,创建一个获取数据库连接的普通类:
DAOClient.java
import java.sql.*;
public class DAOClient {
    public static void 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.*;
public class DAOClient {
    public static void main( String[] args ) {
       Connection conn = getConnection();
       System. out .println( conn.toString() );
    }
    /**
      * 得到一个 Connection 对象
      * @return java.sql.Connection
      */
    private static 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.*;
public class OracleDAOFactory {
    private OracleDAOFactory() {}
    /**
      * 返回一个 OracleDAOFactory 对象
      * @return OracleDAOFactory 类型对象
      */
    public static OracleDAOFactory newInstance() {
       return new OracleDAOFactory();
    }
    /**
      * 得到一个 Connection 对象
      * @return java.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 {
    public static void 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;
public class OracleDAOFactory {
    private static 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 对象
      * @return OracleDAOFactory 类型对象
      */
    public static OracleDAOFactory newInstance() {
       return new OracleDAOFactory();
    }
    /**
      * 得到一个 Connection 对象
      * @return java.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;
public abstract class DAOFactory {
    public static final int ORACLE = 1;
    public static final int SQLSERVER = 2;
    public static final int MYSQL = 3;
   
    public abstract Connection getConnection();
 
    public static DAOFactory getDAOFactory( int dbType ) {
       switch ( dbType ) {
       case ORACLE :
           return OracleDAOFactory.newInstance();
       case SQLSERVER :
           return SqlDAOFactory.newInstance();
       case MYSQL :
           return MySqlDAOFactory.newInstance();
       default :
           return null ;
       }
    }
}
SqlDAOFactory.java
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class SqlDAOFactory extends DAOFactory {
    private static 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 对象
      * @return SqlDAOFactory 类型对象
      */
    public static SqlDAOFactory newInstance() {
       return new SqlDAOFactory();
    }
    /**
      * 得到一个 Connection 对象
      * @return java.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;
public class MySqlDAOFactory extends DAOFactory {
    private static 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 对象
      * @return MySqlDAOFactory 类型对象
      */
    public static MySqlDAOFactory newInstance() {
       return new MySqlDAOFactory();
    }
    /**
      * 得到一个 Connection 对象
      * @return java.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 );
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值