抽象工厂源码解析
public interface Connection extends Wrapper, AutoCloseable 數(shù)據(jù)庫連接的一個接口,本身它是一個接口,這里面有很多方法,很多方法很自然也都是抽象方法,實(shí)現(xiàn)這個接口的類要進(jìn)行實(shí)現(xiàn),Statement createStatement() throws SQLException;這里面返回了Statement,下面接著看,他又返回了PreparedStatement prepareStatement(String sql) throws SQLException;他又返回PreparedStatement,很容易理解,在這個Connection接口里面,返回的都屬于同一個產(chǎn)品族,例如我們創(chuàng)建一個MYSQL的Connection,或者SQLSERVER,從這個連接獲取的無論是PreparedStatement還是Statement,都是連接,也就是說mysql去獲取的時候,肯定是獲取MYSQL連接的Statement,如果調(diào)用prepareStatement這個方法肯定是獲取MYSQL連接的PreparedStatement,所以這里面定義的各種獲取方法,他們都屬于同一個產(chǎn)品族,同理我們再看一個類,還是java.sql這個包下的,有一個Statement這個類,也就是剛才那個方法的返回值,首先我們看一下這個也是一個接口,public interface Statement extends Wrapper, AutoCloseable這里面executeQuery返回一個ResultSet,executeUpdate返回一個int,下面返回也是同一個Statement,很明顯這里也是一個抽象工廠,這里面的所有方法都需要子類來實(shí)現(xiàn),并且只要是從這個Statement獲取的時候,獲取的肯定是同一個產(chǎn)品族,我們看到他有很多實(shí)現(xiàn)類,同理Connection也有很多實(shí)現(xiàn)類,例如我們這里導(dǎo)入了MYSQL的驅(qū)動,我們看一下,只要我們從MYSQL實(shí)現(xiàn)里面獲取
一定要是屬于MYSQL產(chǎn)品族的,MYSQL這里就可以理解什么是抽象工廠,所以在Connection和Statement這里面呢,我們很清楚的理解到什么是抽象工廠,以及在JDK中怎么使用,我們看一下Mybatis的,這里也是一個接口
但是我們注意到,這里面不僅僅返回SqlSession,還要返回Configuration,那很明顯,只要通過SqlSessionFactory,去獲取的兩種類型,肯定是屬于同一個產(chǎn)品族,無論是mysql的sqlSessionFactory,還是SQLSERVER的sqlSessionFactory,獲取的產(chǎn)品也都是屬于同一個產(chǎn)品族,我們看一下他的實(shí)現(xiàn)類,實(shí)現(xiàn)類有兩個,一個是默認(rèn)的SqlSessionFactory,還有SqlSessionManager這兩個類,那這兩個類肯定實(shí)現(xiàn)了他們這兩個方法,其實(shí)SqlSession是Mybatis工作的一個核心,SqlSessionFactory創(chuàng)建的是SqlSession,我們進(jìn)來看一下,我們看一下方法,只能非常多
包括執(zhí)行SQL,獲取mapper,管理事務(wù),包括這里面的rollback,他比較類似于Mysql的connection對象,那之前我們也看了,SqlSession里面有很多重載方法,包括支持AutoCommit,使用ExecutorType,關(guān)于事務(wù)的一些處理,通過這些來構(gòu)建核心的SqlSession對象
那我們看一下,在默認(rèn)的SqlSessionFactory里面,是怎么使用的,我們打開這個實(shí)現(xiàn)類,我們打開openSession,這里面有很多重載的方法
我們找一個帶事務(wù)的吧,我們看一下,通過這個方法我們來研究一下
這工廠怎么產(chǎn)生一個產(chǎn)品,我先從configration里面去獲取環(huán)境變量,然后初始化這個事務(wù)工廠,對他進(jìn)行賦值,再獲取Transaction,然后再通過transaction作為他的入?yún)?獲取一個Executor,然后再通過配置,executor,和autoCommit,這三個參數(shù)來構(gòu)建默認(rèn)的DefaultSqlSession,那也就是說在這個方法里面,返回值是SqlSession,實(shí)際返回的是DefaultSqlSession,那明顯這兩個類之間就是抽象工廠,這么一個模式,比較典型,希望通過這一段源碼解析,能帶來更好的吸收和理解
package com.learn.design.pattern.creational.abstractfactory;/*** 再創(chuàng)建一個手記的class* 那這兩個類呢也都是抽象類* * * @author Leon.Sun**/
public abstract class Article {public abstract void produce();
}
package com.learn.design.pattern.creational.abstractfactory;/*** 創(chuàng)建這個Video class* * * @author Leon.Sun**/
public abstract class Video {public abstract void produce();}
package com.learn.design.pattern.creational.abstractfactory;/*** 創(chuàng)建抽象類和接口的一個業(yè)務(wù)場景的選擇* 那在我們這里面呢* 我們會聲明兩個方法* 一個是獲取視頻* 一個是獲取手記* 而這兩個都是抽象方法* 使用抽象類也是OK的* 只不過這兩種我們都來體會一下* 我們寫兩個方法* * 課程是視頻加手記* 才可以稱之為內(nèi)容* 那么我們就聲明一個產(chǎn)品族的一個工廠* 我們聲明Java課程的一個工廠* * * @author Leon.Sun**/
public interface CourseFactory {Video getVideo();Article getArticle();}
package com.learn.design.pattern.creational.abstractfactory;/*** 他呢繼承Video* * * @author Leon.Sun**/
public class JavaVideo extends Video {@Overridepublic void produce() {System.out.println("錄制Java課程視頻");}
}
package com.learn.design.pattern.creational.abstractfactory;/*** 他呢繼承Article這個類* * * @author Leon.Sun**/
public class JavaArticle extends Article {/*** 然后實(shí)現(xiàn)produce方法* */@Overridepublic void produce() {System.out.println("編寫Java課程手記");}
}
package com.learn.design.pattern.creational.abstractfactory;/*** 他來實(shí)現(xiàn)CourseFactory* 那現(xiàn)在我們要找到具體的Java視頻和Java手記* 那我們繼續(xù)聲明類* * 我們使用抽象工廠的時候* 并沒有聲明視頻的工廠和手記的工廠* 而是聲明一個組合到一起的課程的工廠* 但是具體的產(chǎn)品是有的* Java手記和Java視頻* Java課程作為產(chǎn)品族* 他包含視頻和手記* 那我們接著寫一套Python的* * @author Leon.Sun**/
public class JavaCourseFactory implements CourseFactory {@Overridepublic Video getVideo() {/*** 這里直接返回JavaVideo* */return new JavaVideo();}@Overridepublic Article getArticle() {/*** 這里就直接返回JavaArticle* */return new JavaArticle();}
}
package com.learn.design.pattern.creational.abstractfactory;/*** PythonVideo繼承Video* 然后再寫一個Pathon的手記* * @author Leon.Sun**/
public class PythonVideo extends Video {@Overridepublic void produce() {System.out.println("錄制Python課程視頻");}
}
package com.learn.design.pattern.creational.abstractfactory;/*** 繼承Article* * * @author Leon.Sun**/
public class PythonArticle extends Article {@Overridepublic void produce() {System.out.println("編寫Python課程手記");}
}
package com.learn.design.pattern.creational.abstractfactory;/*** 我們再創(chuàng)建一個Pathon的課程工廠* 他呢實(shí)現(xiàn)課程工廠CourseFactory* 然后把里面的具體實(shí)現(xiàn)* 寫一下* 當(dāng)我們要擴(kuò)展課程的時候* 只需要創(chuàng)建產(chǎn)品族的一個工廠* 還有具體的產(chǎn)品就可以* 現(xiàn)在我們對整體的抽象工廠我們看一下* 我們看一下類圖* * * @author Leon.Sun**/
public class PythonCourseFactory implements CourseFactory {@Overridepublic Video getVideo() {/*** 這里直接new一個PythonVideo*/return new PythonVideo();}@Overridepublic Article getArticle() {/*** 這里直接new一個PythonArticle* */return new PythonArticle();}
}
package com.learn.design.pattern.creational.abstractfactory;import java.sql.Connection;/*** 都是一個產(chǎn)品族* 注意一定要強(qiáng)調(diào)產(chǎn)品族的概念* 在抽象工廠這個設(shè)計(jì)模式當(dāng)中* 那我們來看一下UML* * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 我們創(chuàng)建一個CourseFactory* 我們new一個JavaCourseFactory* * */CourseFactory courseFactory = new JavaCourseFactory();/*** 這個Video我們直接從courseFactory里面去取* * */Video video = courseFactory.getVideo();/*** 這個手記我也是直接從courseFactory去取* 只要從這個工廠里面取的* 肯定都是Java產(chǎn)品族的* * */Article article = courseFactory.getArticle();video.produce();article.produce();Connection c = null;}
}
?
總結(jié)