一、設計模式
在軟體工程領域,設計模式是一套通用的可複用的解決方案,用來解決在軟體設計過程中産生的通用問題。它不是一個可以直接轉換成源代碼的設計,隻是一套在軟體系統設計過程中程式員應該遵循的最佳實踐準則。
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的執行。具體實作可以看我上篇文章的源碼分析。