Builder构建者模式
概念
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数能包含的范围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用更加复杂的对象的构建,甚至只会构建产品的一个部分,直白来说,就是使用多个简单的对象一步一步构建成一个复杂的对象
例子
构建步骤
- 将需要构建的目标类分成多个部件(电脑可以分为主机、显示器、键盘、音响等部件)
- 创建构建类
- 依次创建部件
- 将部件组装成目标对象
MyBatis中的体现
工厂模式
概念
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,属于创建类模式
在简单工厂模式中,可以根据参数的不同返回不同类的实例,简单工厂模式专门定义了一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类
例子:生产电脑
创建抽象产品类
Computer.java
public abstract class Computer {
/**
* 产品的抽象方法,由具体产品类去实现
*/
public abstract void start();
}
创建具体产品类
public class HpComputer extends Computer {
@Override
public void start() {
System.out.println("惠普电脑启动");
}
}
public class LenovoComputer extends Computer {
@Override
public void start() {
System.out.println("联想电脑启动");
}
}
创建工厂类
public class ComputerFactory {
public static Computer createComputer(String type){
Computer computer =null;
switch (type){
case "lenovo":
computer = new LenovoComputer();
case "hp":
computer = new HpComputer();
}
return computer;
}
}
代理模式
概念
代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的的引用,代理模式的英文叫做Proxy,是一种对象结构类模式,代理模式分为静态代理和动态代理
例子
新建一个接口
/**
*抽象类人
*/
public interface Person {
void doSomething();
}
实现类,使其实现抽象方法
/**
*创建一个名为Bob的人的实现类
*/
public class Bob implements Person {
public void doSomething() {
System.out.println("Bob doing something!");
}
}
创建JDK动态代理类,使其实现InvocationHandler接口
public class JDKDynamicProxy implements InvocationHandler {
// 声明被代理的对象
private Person person;
//构造函数
public JDKDynamicProxy(Person person) {
this.person = person;
}
//获取代理对象
public Object getTarget(){
Object proxyInstance = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
return proxyInstance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("对原方法进行了前置增强");
//原方法执行
Object invoke = method.invoke(person, args);
System.out.println("对原方法进行了后置增强");
return invoke;
}
}
MyBatis体现
代理模式可以认为是MyBatis的核心使用模式,正式由于这个模式,我们只需要编写Mapper.java接口,不需要实现,由MyBatis后台帮我们完成具体SQL的执行。
当我们使用Configuration的getMapper方法时,会调用mapperRegisry.getMapper方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来生成一个具体的代理。
/**
* Mapper Proxy 工厂类
*
* @author Lasse Voss
*/
public class MapperProxyFactory<T> {
/**
* Mapper 接口
*/
private final Class<T> mapperInterface;
/**
* 方法与 MapperMethod 的映射
*/
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethod> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
//MapperProxyFactory类中的newInstance方法
public T newInstance(SqlSession sqlSession) {
// 创建了JDK动态代理的invocationHandler接口的实现类mapperProxy
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
// 调用了重载方法
return newInstance(mapperProxy);
}
}
在这里,先通过T newInstance(SqlSession sqlSession)方法会得到一个MapperProxy对象,然后调用T newInstance(MapperProxy mapperProxy)生成代理对象然后返回。
public class MapperProxy<T> implements InvocationHandler, Serializable {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
非常典型的,gaiMapperProxy类实现了InvocationHandler接口,并且实现了该接口的invoke方法,通过这种方式,我们只需要编写Mapper.java接口类,当真正执行一个Mapper接口时,就会转发给MapperProxy.invoke方法,而该方法则会调用后续的sqlSession.curd>executor.execute>prepareStatement等一系列方法,完成SQL的执行和返回