一、设计模式
在软件工程领域,设计模式是一套通用的可复用的解决方案,用来解决在软件设计过程中产生的通用问题。它不是一个可以直接转换成源代码的设计,只是一套在软件系统设计过程中程序员应该遵循的最佳实践准则。
Mybatis源码中使用了大量的设计模式,通过观察设计模式在源码中的应用,能够更深入的理解设计模式。
结合前面源码的分析,我们这里只介绍Build构建者模式、工厂模式和代理模式。
1,Build构建者模式
Builder构建者模式指:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和Build构建模式。相对于工厂模式会产出一个完整的产品,Build应用于更加复杂的对象的构建,甚至只会构建产品的一个部分,直白来说,就是使用多个简单的对象一步一步构建成一个复杂的对象。
例子:使用构建者模式来生产Computer。主要步骤:
(1)将需要构建的目标类分成多个部件(电脑可以分成主机、显示器、键盘、音响等)。
(2)创建构建类
(3)依次创建部件
(4)将部件组装成目标对象
目标对象Computer(一般来说这里面包含的也是对象,我们就全部以String类型例子来讲)
public class Computer {
// 显示器
private String displayer;
// 主机
private String mainUnit;
// 鼠标
private String mouse;
// 键盘
private String keyboard;
//省略set get方法
}
构建者ComputerBuilder
public class ComputerBuilder {
private Computer computer = new Computer();
public void installDisplayer(String displayer){
computer.setDisplayer(displayer);
}
public void installMainUnit(String mainUnit){
computer.setMainUnit(mainUnit);
}
public void installmouse(String mouse){
computer.setMouse(mouse);
}
public void installkeyboard(String keyboard){
computer.setKeyboard(keyboard);
}
public Computer build(){
return computer;
}
}
测试类
public class ConsructorTest {
public static void main(String[] args) {
ComputerBuilder computerBuilder = new ComputerBuilder();
computerBuilder.installDisplayer("显示器");
computerBuilder.installMainUnit("主机");
computerBuilder.installmouse("鼠标");
computerBuilder.installkeyboard("键盘");
Computer computer = computerBuilder.build();
System.out.println(computer);
}
}
Mybatis中的体现:在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的sqlMapConfig.xml和所有的*Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将Configuration对象作为参数构建一个DefaultSqlSessionFactory对象。
parser.parse()方法中是解析配置文件中所有信息并封装到Configuration中,从而构建出复杂Configuration对象。
2,工厂模式
在Mybatis中比如SqlSessionFactory使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂模式(静态工厂方法模式),属于创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
例子:生产电脑
假设有一个电脑的代工生产商,它目前已经可以代工生产联想电脑了,随着业务的扩展,这个代工生产上还要生产惠普的电脑,我们就需要一个单独的类来专门生产电脑,这就用到了简单工厂模式。
(1)创建抽象产品类
public abstract class Computer {
public abstract void start();
}
(2)创建具体产品类(它们都继承了父类Computer,并实现了了start()方法)
public class LenovoComputer extends Computer {
@Override
public void start() {
System.out.println("联想电脑启动");
}
}
public class HpComputer extends Computer {
@Override
public void start() {
System.out.println("惠普电脑启动");
}
}
(3)创建工厂类
接下来创建一个工厂类,它提供一个静态方法createComputer用来生产电脑。你只需要传入你想生产电脑的品牌,它就会实例化相应品牌的电脑对象
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;
}
}
Mybatis中的体现:Mybatis中执行sql语句、获取Mappers、管理事务的核心接口SqlSession的创建过程使用到了工厂模式。有一个SqlSessionFactory来负责创建SqlSession。
我们可以看到,该Factory的openSession()方法重载了好多个,支持传入不同的参数来创建SqlSession对象。
3,代理模式
代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫Proxy,它是一种对象结构型模式,代理模式分为静态代理和动态代理。我们这里介绍动态代理。
例子:创建一个Person接口,并创建一个doSomething()方法:
public interface Person {
public void doSomething();
}
创建一个名为Bob的Person接口的实现类,并重写doSomething()方法:
public class Bob implements Person {
@Override
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;
}
}
接下来编写一个测试类测试:
public class proxyTest {
public static void main(String[] args) {
System.out.println("不使用代理类,调用doSomething");
Person person = new Bob();
person.doSomething();
System.out.println("--------------------------");
System.out.println("使用代理类,调用doSomething");
Person proxy = (Person) new JDKDynamicProxy(new Bob()).getTarget();
proxy.doSomething();
}
}
我们可以看到打印结果:
Mybatis中的体现:代理模式可以认为是Mybatis的核心使用的模式,正是由于这个模式,我们只需要编写Mapper接口,不需要实现,有Mybatis帮我们完成具体sql的执行。具体实现可以看我上篇文章的源码分析。