题目分析

  • 配置文件保存多种数据库连接的信息,比如数据库用户名密码等信息,并且可以根据配置文件来切换数据库
  • 有一个简单工厂来生成数据库的连接信息,具体的数据库操作延迟到子类中进行,外部类不知道具体的创建细节
  • 工厂中先去读取配置文件,先判断要使用哪种数据库,然后去加载对应的数据库配置信息,并通过反射加载驱动,获得连接
  • 外部在获取dao接口实例的时候不需要知道具体的创建细节,只需要去用就行

UML图

项目结构

代码

  • 数据库配置文件config.properties
#在这里修改数据库的类型
DatabaseType=MySQL
#MySQL连接信息
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/card
mysql.username=root
mysql.password=root
#Oracle连接信息
oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:card
oracle.username=root
oracle.password=root
  • 对应数据库user表的User实体类
/** * @ClassName: bean.User * @Author: Leo * @Description: 对应数据表的User实体类 * @Date: 6/1/2019 1:54 PM */
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    /** * 用户名 */
    private String username;

    /** * 密码 */
    private String password;

    /** * 登录状态 */
    private Integer status;

    public User() {
    }

    public User(String username, String password, Integer status) {
        this.username = username;
        this.password = password;
        this.status = status;
    }
	//此处省略Get/Set方法
}
  • User dao接口
/** * @ClassName: IUser * @Author: Leo * @Description: dao接口 * @Date: 6/1/2019 2:18 PM */
public interface IUser {

    void insert(User user);

    void update(User user);

    void delete(String username);

    void select(String username);
}

  • 使用MySQL数据库-增删查改
/** * @ClassName: MySQLUser * @Author: Leo * @Description: 使用MySQL数据库-增删查改 * @Date: 6/1/2019 2:19 PM */
public class MySQLUser implements IUser {
    private Connection connection;

    public MySQLUser(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void insert(User user) {
        String sql = "INSERT INTO user(username,password,status) values(?,?,?)";
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, user.getUsername());
            preparedStatement.setString(2, user.getPassword());
            preparedStatement.setInt(3, user.getStatus());
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void update(User user) {
        //原理同上,不再赘述
    }

    @Override
    public void delete(String username) {
        //原理同上,不再赘述
    }

    @Override
    public void select(String username) {
        //原理同上,不再赘述
    }
}

  • 使用Oracle数据库-增删查改
/** * @ClassName: OracleUser * @Author: Leo * @Description: 使用Oracle数据库-增删查改 * @Date: 6/1/2019 2:19 PM */
public class OracleUser implements IUser {
    private Connection connection;

    public OracleUser(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void insert(User user) {
        //原理同上,不再赘述
    }

    @Override
    public void update(User user) {
        //原理同上,不再赘述
    }

    @Override
    public void delete(String username) {
        //原理同上,不再赘述
    }

    @Override
    public void select(String username) {
        //原理同上,不再赘述
    }
}

  • 测试类
/** * @ClassName: Main * @Author: Leo * @Description: 测试类 * @Date: 6/1/2019 1:11 PM */
public class Main {
    public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
        //创建对应的数据库工厂 用来生成对应的Dao接口
        DataBaseFactory factory = new DataBaseFactory();
        //MySQL 插入一条记录
        IUser iUser = factory.createMySQLUser();
        iUser.insert(new User("Test", "123", 1));
        //Oracle 插入一条记录
        iUser = factory.createOracleUser();
        iUser.insert(new User("Test", "123", 1));
    }
}

  • 运行结果

总结:

  1. 该模式的优缺点,特别从开闭原则论述
  • 简单工厂模式可以隐藏对象的创建细节:如果在生成一个对象的时候,有很多步骤或者复杂的操作,可以考虑通过简单工厂封装创建对象的步骤,隐藏创建的过程,在这里就隐藏了连接数据库的具体细节,对外做到透明。
  • 如果创建对象仅仅是通过new的方式就可以创建,那么不应该去使用工厂模式,否则会增加维护一个工厂类。
  • 只需要修改配置文件的头部信息,就可以修改使用的数据库,避免了在代码内部修改时需要二次编译,在配置文件中修改,可以在运行期间进行。
  1. 编程中遇到的问题及解决方法
  • 好像没有遇到问题
  • 说一下应用场景:Log4J,MyBatis等都可以使用配置文件的方式,在运行期间修改参数