`

从最初的状态 一步一步重构出dao模式

    博客分类:
  • java
阅读更多

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

分享到:
评论
1 楼 hnzhoujunmei 2010-09-08  
,代码不是很方便看

相关推荐

    重构DAO

    重构DAO DAO(Data Access Object)模式是一种常用的设计模式,旨在抽象和封装对数据源的访问。通过使用DAO模式,可以降低商业逻辑层和数据访问层的耦合度,提高应用的可维护性和可移植性。 1. DAO模式的优点 ...

    如何重构DAO模式

    ### 如何重构DAO模式 #### 一、引言 数据访问对象(DAO,Data Access Object)模式是一种在软件开发中非常流行的模式,特别是在那些需要处理大量数据的应用程序中。通过抽象和封装对数据源的所有访问操作,DAO模式...

    如何重构DAO模式源文件

    总之,重构DAO模式源文件是一个旨在提升代码质量和可维护性的过程。通过合理地设计接口、消除冗余、解耦合和利用设计模式,我们可以让代码更加健壮,便于团队协作和长期维护。同时,不要忘记在整个重构过程中保持...

    [电子书] 重构与模式

    在《重构与模式》中,作者深入浅出地讲解了重构的基本原则、步骤和技巧,帮助读者掌握如何在项目中安全、系统地实施重构。 模式,另一方面,是软件设计中的一个关键概念,它是在特定上下文中解决常见问题的最佳实践...

    j2ee重构DAO&MVC等模式.ppt

    本文主要探讨了Java开发中的几种常见设计模式:简单工厂、工厂模式、单例模式、DAO模式以及MVC模式。这些模式在实际项目中扮演着重要角色,有助于提高代码的可维护性和灵活性。 首先,简单工厂模式是一种用于创建...

    重构与模式2.pdf

    ### 重构与模式的核心知识点解析 #### 一、重构与模式的关系 《重构与模式》这本书探讨了重构和设计模式之间的内在联系。重构是指在不改变软件外部行为的前提下,对软件内部结构进行调整,以提高代码质量的过程。...

    从重构到模式(英文版)

    《从重构到模式》是Addison Wesley出版社出版的一本关于软件开发进阶的书籍,英文原版名为"Refactoring To Patterns"。这本书的核心主题是探讨如何通过重构代码来逐步引入设计模式,提升软件的可读性、可维护性和可...

    设计模式重构代码

    3. **状态模式**:如果审批过程有多个状态变化,并且每个状态对应不同的行为,那么状态模式可以用来表示状态之间的转换和行为,使代码更易于管理。 4. **观察者模式**:在审批流程中,可能需要通知相关人员审批结果...

    运用DAO和对象化进行重构_项目教程(2)_复习

    总之,这个教程对于想要深入理解DAO设计模式、对象化编程以及重构技巧的.NET开发者来说是一份宝贵的资源。通过学习和实践,开发者能够提高代码质量,降低维护成本,并且能够更好地应对未来技术的变化。

    重构与模式.[美]Joshua Kerievsky(带详细书签).pdf

    本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新方法,而且有助于读者结合...

    重构与模式.pdf

    9. **移除设置器**(Remove Setting Method):如果一个对象的状态变化过于频繁,可以考虑移除设置器方法,改用构造函数或工厂模式初始化对象状态。 10. **引入中间类**(Introduce Middle Class):当两个类之间...

    05-JDBC-Dao重构.xmind

    DAO重构

    软件设计模式与重构大作业-心算大师游戏

    3. **开放封闭原则的应用**:通过抽象出游戏模式和难度,使用策略模式或者工厂模式,使得添加新难度无需修改原有代码。 4. **消除重复代码**:提取共性功能为单独的方法或类,例如创建一个通用的事件监听处理方法。...

    设计模式与重构(design pattern )

    设计模式是经验丰富的开发者们在解决常见问题时总结出的最佳实践,而重构则是在不改变软件外部行为的前提下,优化其内部结构的过程。 设计模式: 设计模式不是具体的代码或库,而是一种在特定情况下解决问题的模板...

    设计模式与重构

    主要分为三类:创建型模式(如单例、工厂方法、抽象工厂)、结构型模式(如适配器、装饰器、代理、桥接、组合、外观、享元)和行为型模式(如策略、模板方法、观察者、迭代器、访问者、命令、责任链、备忘录、状态、...

    代码重构&模式

    3. **行为型模式**:如策略、模板方法、观察者、访问者、迭代器、责任链、命令、备忘录、状态、解释器模式,它们关注对象之间的交互和职责分配。 例如,**单例模式**确保一个类只有一个实例,并提供一个全局访问点...

    用Java编写的状态模式代码,有重构前后的代码比较

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且在不同的状态下,对象的行为也相应地变化。 首先,我们来理解状态模式的...

    重构与模式 清晰.pdf

    本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新方法,而且有助于读者结合...

    重构与模式(jb51.net).pdf

    例如,从单体架构重构为微服务架构,或者是从传统的数据库设计转变为NoSQL的数据处理模式。 此外,良好的重构习惯可以帮助开发人员避免所谓的技术债务。技术债务是指为了快速交付软件而采取的一些捷径,这些捷径...

Global site tag (gtag.js) - Google Analytics