1、簡單工廠(Simple Factory)
概述:
在創建一個對象時不向客戶暴露內部細節,並提供一個創建對象的通用接口。
錯誤的方式:
正確的方式:
簡單工廠把實例化的操作單獨放到一個類中,這個類就成爲簡單工廠類,讓簡單工廠類來決定應該用哪個具體子類來實例化。
這樣做能把客戶類和具體子類的實現解耦,客戶類不再需要知道有哪些子類以及應當實例化哪個子類。客戶類往往有多個,如果不使用簡單工廠,那麼所有的客戶類都要知道所有子類的細節。而且一旦子類發生改變,例如增加子類,那麼所有的客戶類都要進行修改。
注:並不是GOF23種設計模式
In JDK:
Calendar
-createCalendar()
2、工廠方法(Factory Method)
概述:
定義了一個創建對象的接口,但由子類決定要實例化哪個類。工廠方法把實例化操作推遲到子類。
public abstract class Factory {
abstract public Product factoryMethod();
public void doSomething() {
Product product = factoryMethod();
// do something with the product
}
}
public class ConcreteFactory extends Factory {
public Product factoryMethod() {
return new ConcreteProduct();
}
}
public class ConcreteFactory1 extends Factory {
public Product factoryMethod() {
return new ConcreteProduct1();
}
}
public class ConcreteFactory2 extends Factory {
public Product factoryMethod() {
return new ConcreteProduct2();
}
}
在簡單工廠中,創建對象的是另一個類,而在工廠方法中,是由子類來創建對象。
上圖中,Factory 有一個 doSomething() 方法,這個方法需要用到一個產品對象,這個產品對象由 factoryMethod() 方法創建。該方法是抽象的,需要由子類去實現。
使用場景:
創建對象需要大量重複的代碼
客戶端( 應用層)不需要依賴產品類實例如何創建、實現等細節
一個類通過其子類來指定創建哪個對象
優點:
用戶只需要關心所需產品對應的工廠,無須關心創建細節 加入新產品符合開閉原則,提高可擴展性
缺點:
類的個數容易過多,增加複雜度 增加了系統的抽象性和理解難度
In JDK
Collection
~iterator()
ArrayList
+iterator()
3、抽象工廠(Abstract Factory)
概述:
適用場景:
客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節
強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重複的代碼
提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現
優點:
具體產品在應用層代碼隔離,無須關心創建細節,將一個系列的產品族統一到一起創建
缺點:
規定了所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠的接口
增加了系統的抽象性和理解難度
關於抽象工廠的產品族:
提供一個接口,用於創建相關的對象家族
UML&實例DEMO
源碼鏈接:https://github.com/NoSuchClass/design_pattern/tree/master/src/creational/abstractfactory
抽象工廠模式創建的是產品族,也就是很多對象而不是一個對象,並且這些對象是相關的,也就是說必須一起創建出來。而工廠方法模式只是用於創建一個對象,這和抽象工廠模式有很大不同。
抽象工廠模式用到了工廠方法模式來創建單一對象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是讓子類來實現,這兩個方法單獨來看就是在創建一個對象,這符合工廠方法模式的定義。
至於創建對象的家族這一概念是在 Client 體現,Client 要通過 AbstractFactory 同時調用兩個方法來創建出兩個對象,在這裏這兩個對象就有很大的相關性,Client 需要同時創建出這兩個對象。
從高層次來看,抽象工廠使用了組合,即 Cilent 組合了 AbstractFactory,而工廠方法模式使用了繼承。
In JDK
java.sql.Connection:
這就是一個抽象工廠,裏面都是一個產品族的獲取
java.sql.Statement
In MyBatis
java.sql.SqlSessionFactory:
這兒不但獲取了SqlSession,還獲取了Configuration,是同一產品族