在介紹抽象工廠之前经瓷,我們先了解以下概念
產(chǎn)品等級
對于Cpu,有高通生產(chǎn)的Cpu绘雁,華為生產(chǎn)的麒麟Cpu橡疼,以及聯(lián)發(fā)科的MTK Cpu,它們都屬于Cpu這同一產(chǎn)品等級庐舟。對于空調(diào)欣除,由美的空調(diào)、海爾空調(diào)挪略,他們也屬于同一個產(chǎn)品等級
產(chǎn)品族
由一個工廠生產(chǎn)的不同等級的產(chǎn)品構(gòu)成了一個產(chǎn)品族历帚,美的公司生產(chǎn)空調(diào)、電冰箱瘟檩、洗衣機抹缕,這些產(chǎn)品構(gòu)成了一個產(chǎn)品族。
抽象工廠和工廠模式最大的區(qū)別是
工廠模式解決的同一產(chǎn)品等級的問題
抽象共產(chǎn)解決的是產(chǎn)品族的問題
抽象工廠的定義
抽象工廠提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口
我們在使用時不需要知道或關(guān)心它從這些工廠方法中獲得對象的具體類型墨辛,因為我們客戶端程序僅使用這些對象的通用接口
抽象工廠具體實現(xiàn)
- 首先定義兩個產(chǎn)品等級卓研,空調(diào)(AirConditioningSystem)和洗衣機(Refrigerator)。其中美的工廠生產(chǎn)美的洗衣機和美的空調(diào)睹簇,海爾工廠生產(chǎn)海爾洗衣機和海爾空調(diào)奏赘。
public interface AirConditioningSystem
{
void produce();
}
public class HaierAirConditioningSystem implements AirConditioningSystem
{
@Override
public void produce()
{
System.out.println("海爾空調(diào)");
}
}
public class MideaAirConditioningSystem implements AirConditioningSystem
{
@Override
public void produce()
{
System.out.println("美的空調(diào)");
}
}
public interface Refrigerator
{
void produce();
}
public class MideaRefrigerator implements Refrigerator
{
@Override
public void produce()
{
System.out.println("美的冰箱");
}
}
public class HaierRefrigerator implements Refrigerator
{
@Override
public void produce()
{
System.out.println("海爾冰箱");
}
}
- 定義工廠類
public interface JiadianFactory
{
Refrigerator produceRefrigetor();
AirConditioningSystem produceAirConditioningSystem();
}
public class HaierJiadianFactory implements JiadianFactory
{
@Override
public Refrigerator produceRefrigetor()
{
return new HaierRefrigerator();
}
@Override
public AirConditioningSystem produceAirConditioningSystem()
{
return new HaierAirConditioningSystem();
}
}
public class MideaJiadianFactory implements JiadianFactory
{
@Override
public Refrigerator produceRefrigetor()
{
return new MideaRefrigerator();
}
@Override
public AirConditioningSystem produceAirConditioningSystem()
{
return new MideaAirConditioningSystem();
}
}
- 定義客戶類
public class Client
{
public static void main(String[] args)
{
JiadianFactory jiadianFactory = new HaierJiadianFactory();
JiadianFactory jiadianFactory2 = new MideaJiadianFactory();
Refrigerator refrigerator = jiadianFactory.produceRefrigetor();
AirConditioningSystem airConditioningSystem = jiadianFactory.produceAirConditioningSystem();
refrigerator.produce();
airConditioningSystem.produce();
}
}
這樣我們應(yīng)用層的代碼是和具體的空調(diào)以及電冰箱是解耦的。我們在客戶類里并沒由導(dǎo)入海爾空調(diào)以及海爾電冰箱的類太惠。
其UML類圖如下
優(yōu)點
- 應(yīng)用層代碼不和具體的產(chǎn)品進行依賴磨淌,它只和具體的工廠發(fā)生依賴關(guān)系
- 擴展性好,當(dāng)我們新增具體的產(chǎn)品時凿渊,只需要增加其對應(yīng)的工廠梁只,并不需要修改其他類的代碼
缺點
- 新增產(chǎn)品等級比較麻煩,需要修改對應(yīng)的工廠接口以及每一個實現(xiàn)類
- 增加了系統(tǒng)的抽象性和理解難度
使用場景
- 應(yīng)用層不依賴與產(chǎn)品類實例如何創(chuàng)建埃脏、實現(xiàn)細節(jié)
- 強調(diào)一系列相關(guān)的產(chǎn)品對象(屬于同一-產(chǎn)品族)一起使用創(chuàng)建對象需要大量重復(fù)的代碼
- 提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實現(xiàn)
應(yīng)用
jdbc中的Connection
jdbc中的Connection為一個接口搪锣,里面有許多方法,這里我們挑選幾個
Statement createStatement() throws SQLException;
DatabaseMetaData getMetaData() throws SQLException;
其中這兩個方法返回的Statement和DataBasemetaData均為接口彩掐,其在具體的工廠類中進行實例化构舟。我們可以把Connection理解為抽象工廠類,Statement和DataBasemetaData為產(chǎn)品類堵幽。而每一種數(shù)據(jù)庫驅(qū)動都會有該Connection的自己具體實現(xiàn)類狗超,比如在Mysql中具體實現(xiàn)類為CommectionImpl弹澎,對于這兩個方法,其分別返回了自己的實現(xiàn)類StatementImpl和com.mysql.jdbc.DataBasemetaData努咐。在這里com.mysql.jdbc.DataBasemetaData是java.sql.DataBasemetaData的一個具體實現(xiàn)類
MyBatis中的SqlSessionFactory
mybatis中的SqlSeeionFactory定義如下
我們可以發(fā)現(xiàn)其內(nèi)部定義的方法返回結(jié)果有SqlSession接口和Configuration類對象苦蒿。
SqlSeesionFactory相當(dāng)于一個抽象工廠。而其實現(xiàn)有
DefaultSqlSessionFactory
和SqlSessionManager
渗稍,在這兩個類中我們都可以獲取其對應(yīng)的具體SqlSession和Configuration實現(xiàn)