簡單工廠模式
簡單工廠模式(Simple Factory Pattern)是指由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例,但它不屬于 GOF,23 種設(shè)計模式(參考資料:http://en.wikipedia.org/wiki/Design_Patterns#Patterns_by_Type)。簡單工廠適用于工廠類負(fù)責(zé)創(chuàng)建的對象較少的場景,且客戶端只需要傳入工廠類的參數(shù),對于如何創(chuàng)建對象的邏輯不需要關(guān)心。
首先定義一個接口作為產(chǎn)品的標(biāo)準(zhǔn),然后創(chuàng)建產(chǎn)品類實現(xiàn)接口并根據(jù)各個產(chǎn)品的特性實現(xiàn)產(chǎn)品并用簡單工廠進(jìn)行管理。
課程接口:
public interface ICourse {
/**
* 錄制視頻
* @return
*/
void record();
}
Java課程:
public class JavaCourse implements ICourse {
public void record() {
System.out.println("錄制Java課程");
}
}
Python課程:
public class PythonCourse implements ICourse {
public void record() {
System.out.println("錄制Python課程");
}
}
創(chuàng)建工廠類使用反射技術(shù)對產(chǎn)品進(jìn)行創(chuàng)建
public class CourseFactory {
public ICourse create(Class<? extends ICourse> clazz){
try {
if (null != clazz) {
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
簡單工廠也有它的缺點(diǎn):工廠類的職責(zé)相對過重,不易于擴(kuò)展過于復(fù)雜的產(chǎn)品結(jié)構(gòu)。
工廠方法模式
工廠方法模式(Fatory Method Pattern)是指定義一個創(chuàng)建對象的接口,但讓實現(xiàn)這個 接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進(jìn)行。在工廠方法 模式中用戶只需要關(guān)心所需產(chǎn)品對應(yīng)的工廠,無須關(guān)心創(chuàng)建細(xì)節(jié),而且加入新的產(chǎn)品符 合開閉原則。 工廠方法模式主要解決產(chǎn)品擴(kuò)展的問題,在簡單工廠中,隨著產(chǎn)品鏈的豐富,如果每個課程的創(chuàng)建邏輯有區(qū)別的話,工廠的職責(zé)會變得越來越多,有點(diǎn)像萬能工廠,并不便于維護(hù)。根據(jù)單一職責(zé)原則我們將職能繼續(xù)拆分,專人干專事。Java 課程由 Java 工廠創(chuàng)建, Python 課程由 Python 工廠創(chuàng)建,對工廠本身也做一個抽象。
ICourseFactory 接口:
public interface ICourseFactory {
ICourse create();
}
創(chuàng)建子工廠,JavaCourseFactory 類:
public class JavaCourseFactory implements ICourseFactory {
public ICourse create() {
return new JavaCourse();
}
}
PythonCourseFactory 類:
public class PythonCourseFactory implements ICourseFactory {
public ICourse create() {
return new PythonCourse();
}
}
看測試代碼:
public class FactoryMethodTest {
public static void main(String[] args) {
ICourseFactory factory = new PythonCourseFactory();
ICourse course = factory.create();
course.record();
factory = new JavaCourseFactory();
course = factory.create();
course.record();
}
}
工廠方法適用于以下場景: 1、創(chuàng)建對象需要大量重復(fù)的代碼。 2、客戶端(應(yīng)用層)不依賴于產(chǎn)品類實例如何被創(chuàng)建、實現(xiàn)等細(xì)節(jié)。 3、一個類通過其子類來指定創(chuàng)建哪個對象。
工廠方法也有缺點(diǎn): 1、類的個數(shù)容易過多,增加復(fù)雜度。 2、增加了系統(tǒng)的抽象性和理解難度。
抽象工廠模式
抽象工廠模式(Abastract Factory Pattern)是指提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,無須指定他們具體的類。客戶端(應(yīng)用層)不依賴于產(chǎn)品類實例如何被創(chuàng)建、實現(xiàn)等細(xì)節(jié),強(qiáng)調(diào)的是一系列相關(guān)的產(chǎn)品對象(屬于同一產(chǎn)品族)一起使用創(chuàng)建對 象需要大量重復(fù)的代碼。需要提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從 而使客戶端不依賴于具體實現(xiàn)。還是以課程為例,課程有了新的標(biāo)準(zhǔn),每個課程不僅要提供課程的錄播視頻,而且還要提供老師的課堂筆記。相當(dāng) 于現(xiàn)在的業(yè)務(wù)變更為同一個課程不單純是一個課程信息,要同時包含錄播視頻、課堂筆 記甚至還要提供源碼才能構(gòu)成一個完整的課程。在產(chǎn)品等級中增加兩個產(chǎn)品 IVideo 錄播 視頻和 INote 課堂筆記。
IVideo 接口:
/**
* 錄播視頻
*/
public interface IVideo {
void record();
}
INote 接口:
/**
* 課堂筆記
*/
public interface INote {
void edit();
}
創(chuàng)建一個抽象工廠 CourseFactory 類:
/**
* 抽象工廠是用戶的主入口
* 在Spring中應(yīng)用得最為廣泛的一種設(shè)計模式
* 易于擴(kuò)展
*/
public interface CourseFactory {
INote createNote();
IVideo createVideo();
}
接下來,創(chuàng)建 Java 產(chǎn)品族,Java 視頻 JavaVideo 類:
/**
* Java視頻
*/
public class JavaVideo implements IVideo {
public void record() {
System.out.println("錄制Java視頻");
}
}
擴(kuò)展產(chǎn)品等級 Java 課堂筆記 JavaNote 類:
/**
* Java筆記
*/
public class JavaNote implements INote {
public void edit() {
System.out.println("編寫Java筆記");
}
}
創(chuàng)建 Java 產(chǎn)品族的具體工廠 JavaCourseFactory:
public class JavaCourseFactory implements CourseFactory {
public INote createNote() {
return new JavaNote();
}
public IVideo createVideo() {
return new JavaVideo();
}
}
然后創(chuàng)建 Python 產(chǎn)品,Python 視頻 PythonVideo 類:
public class PythonVideo implements IVideo {
public void record() {
System.out.println("錄制Python視頻");
}
}
擴(kuò)展產(chǎn)品等級 Python 課堂筆記 PythonNote 類:
public class PythonNote implements INote {
public void edit() {
System.out.println("編寫Python筆記");
}
}
創(chuàng)建 Python 產(chǎn)品族的具體工廠 PythonCourseFactory:
public class PythonCourseFactory implements CourseFactory {
public INote createNote() {
return new PythonNote();
}
public IVideo createVideo() {
return new PythonVideo();
}
}
客戶端調(diào)用:
public class AbstractFactoryTest {
public static void main(String[] args) {
JavaCourseFactory factory = new JavaCourseFactory();
factory.createNote().edit();
factory.createVideo().record();
}
}
上面的代碼完整地描述了兩個產(chǎn)品族 Java 課程和 Python 課程,也描述了兩個產(chǎn)品等級 視頻和手記。抽象工廠非常完美清晰地描述這樣一層復(fù)雜的關(guān)系。但是,不知道大家有 沒有發(fā)現(xiàn),如果我們再繼續(xù)擴(kuò)展產(chǎn)品等級,將源碼 Source 也加入到課程中,那么我們的 代碼從抽象工廠,到具體工廠要全部調(diào)整,很顯然不符合開閉原則。因此抽象工廠也是 有缺點(diǎn)的: 1、規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,產(chǎn)品族中擴(kuò)展新的產(chǎn)品困難,需要修改抽象工廠 的接口。 2、增加了系統(tǒng)的抽象性和理解難度