在Java中,工厂类是一种设计模式,主要用于创建对象的过程。工厂类的目的是将对象的创建逻辑封装在一个类中,以便客户端代码无需了解具体的实现细节,只需要通过工厂类获取所需的实例。
工厂类的主要作用包括:
封装对象创建逻辑: 将对象的创建过程和细节封装在工厂类中,使客户端代码无需关心如何创建对象,降低了代码的耦合性。
统一接口: 工厂类提供了一个统一的接口或方法来创建对象,客户端代码只需要调用这个接口或方法,而无需关心具体的实现类。
简化实例化过程: 对于某些复杂的对象创建过程,工厂类可以隐藏创建对象的复杂性,简化了客户端代码。
灵活切换实现: 如果需要更改或替换某个类的实现,只需修改工厂类的实现,而无需修改客户端代码。这种方式支持更灵活的实现替换。
这是我们之前的代码:
package Mybatis;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
/**
* 我们已经配置好了myBatis,当我们希望使用myBatis的时候,
* 我们就会创建一个SqlSessionFactory类,在这个类里使用myBatis的各种功能。
*/
public class Main {
public static void main(String[] args) throws FileNotFoundException {
//寻找配置文件,参数就是配置文件的路径,这里是相对路径
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(new FileInputStream("myBatis_config.xml"));
//sqlSession就像之前的statement一样,创建一个连接,执行sql语句,它也需要关闭,所以写进try
//参数true代表开启自动提交,如果不自动提交,就类似与之前说的mysql的事务模式
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)){
//这里的参数是mapper里指定的那个sql语句的名称
//也就是UserMapper.xml里的id字段的名称
List<User> student = sqlSession.selectList("selectUser");
//这行代码使用了 Java 8 引入的新特性之一,称为方法引用(Method Reference)。
// 具体来说,System.out::println 是一个静态方法引用,用于将 println 方法关联到 System.out 对象上。
//在这里,System.out::println 等效于 lambda 表达式 (s) -> System.out.println(s)。
// 它表示将遍历 student 集合的每个元素,并将每个元素传递给 System.out.println 方法,实现在控制台上打印每个元素的效果。
student.forEach(System.out::println);
}
}
}
我们发现在之前的代码中,我们首先新建了一个工厂类,然后执行查询。
但是很这里的代码逻辑有些不清晰,我们希望的是? 连接->查询。
我们希望:
MybatisUtil.getSession(true)
而不是:
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(new FileInputStream("myBatis_config.xml"));
工厂类虽然封装对象创建逻辑,但在这里还有些臃肿,所以我们新建一个工具类,来封装这个工厂类。
package Mybatis;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.FileInputStream;
import java.io.IOException;
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try{
sqlSessionFactory=new SqlSessionFactoryBuilder().build(new FileInputStream("myBatis_config.xml"));
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 获取一个新的会话
* @param autoCommit 是否开启自动提交(跟JDBC是一样的,如果不自动提交,则会变成事务操作)
* @return SqlSession对象
*/
public static SqlSession getSession(boolean autoCommit){
return sqlSessionFactory.openSession(autoCommit);
}
}
在这段代码里,有一个静态段和静态变量。静态段和静态变量会在类加载的过程中执行,并且只执行一次。(无论你new多少个MyBatisUtil对象,都只会执行一i,不会重复执行)
这样的MyBatisUtil
写法有几个好处:
单例模式: SqlSessionFactory
是一个比较重量级的对象,包含了对数据库的配置信息、映射信息等,创建和初始化它可能是一个相对耗时的操作。这样写确保在整个应用程序生命周期内只创建了一个 SqlSessionFactory
对象,提高了性能。
全局唯一性: SqlSessionFactory
对象在整个应用程序中是唯一的,保证了全局唯一性。这意味着在应用程序中的任何地方,都可以通过 MyBatisUtil
获取到相同的 SqlSessionFactory
实例。
资源共享: SqlSessionFactory
是一个比较重的资源,通过单例模式,可以确保所有的 SqlSession
对象都共享同一个 SqlSessionFactory
。这样,在应用程序中多个地方需要访问数据库时,共享的 SqlSessionFactory
可以提高资源利用效率。
简化使用: 封装了 SqlSessionFactory
的创建过程,对客户端代码提供了简单的接口,通过 MyBatisUtil
的 getSession
方法,客户端可以方便地获取到一个新的 SqlSession
实例,而无需关心 SqlSessionFactory
的创建和初始化过程。
所以现在,我们的Main类变成了:
package Mybatis;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class MainWithUtil {
public static void main(String args[]){
//用MyBatisUtil来包装之前MainWithoutUtil的工厂类,更简单地得到连接
try(SqlSession sqlSession = MyBatisUtil.getSession(true)){
//这里的参数是mapper里指定的那个sql语句的名称
//也就是UserMapper.xml里的id字段的名称
List<User> student = sqlSession.selectList("selectUser");
//这行代码使用了 Java 8 引入的新特性之一,称为方法引用(Method Reference)。
// 具体来说,System.out::println 是一个静态方法引用,用于将 println 方法关联到 System.out 对象上。
//在这里,System.out::println 等效于 lambda 表达式 (s) -> System.out.println(s)。
// 它表示将遍历 student 集合的每个元素,并将每个元素传递给 System.out.println 方法,实现在控制台上打印每个元素的效果。
student.forEach(System.out::println);
}
}
}