天天看點

Mybatis學習筆記六之設計模式

一、設計模式

        在軟體工程領域,設計模式是一套通用的可複用的解決方案,用來解決在軟體設計過程中産生的通用問題。它不是一個可以直接轉換成源代碼的設計,隻是一套在軟體系統設計過程中程式員應該遵循的最佳實踐準則。

Mybatis源碼中使用了大量的設計模式,通過觀察設計模式在源碼中的應用,能夠更深入的了解設計模式。

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對象。

Mybatis學習筆記六之設計模式

parser.parse()方法中是解析配置檔案中所有資訊并封裝到Configuration中,進而建構出複雜Configuration對象。

Mybatis學習筆記六之設計模式

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。

Mybatis學習筆記六之設計模式

我們可以看到,該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中的展現:代理模式可以認為是Mybatis的核心使用的模式,正是由于這個模式,我們隻需要編寫Mapper接口,不需要實作,有Mybatis幫我們完成具體sql的執行。具體實作可以看我上篇文章的源碼分析。