文章目錄
1. 簡單工廠
1.1 定義
- 簡單工廠是由一個工廠對象創建出哪一種產品類的實例,是創建型的一種但不屬於GOF23中設計模式之一。
1.2 使用場景
- 工廠類負責創建的對象較少。
- 應用層只知道傳入工廠類的參數,對於如何創建對象的邏輯並不關心。
1.3 模擬代碼
-
以錄製視頻爲例,現在有Java課程的視頻,Python的視頻,通過簡單工廠的方式將課程實例化。
-
抽象類Video
package com.fukexin.design.pattern.creational.simplefactory;
public abstract class Video {
public abstract void produce();
}
- 子類JavaVideo繼承於Video
package com.fukexin.design.pattern.creational.simplefactory;
public class JavaVideo extends Video {
public void produce() {
System.out.println("錄製Java課程視頻");
}
}
- 子類PythonVideo繼承於Video
package com.fukexin.design.pattern.creational.simplefactory;
public class PythonVideo extends Video{
public void produce() {
System.out.println("錄製Python課程視頻");
}
}
- 工廠類VideoFactory用於生產具體的Video(使用反射創建實例的好處是符合開閉原則,即對擴展開放,對修改關閉)
package com.fukexin.design.pattern.creational.simplefactory;
import java.lang.reflect.InvocationTargetException;
public class VideoFactory {
public Video getInstance(Class c){
Video video=null;
try {
video= (Video) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return video;
}
}
- UML類圖
1.4 應用源碼解析
- java.util.Calendar中的getIntance()方法調用了createCalendar()方法。會根據傳入的語言和國家來實例化不同的Calendar。
if (cal == null) {
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
- UML類圖
2. 工廠方法
2.1 定義
- 定義一個創建對象的接口,但讓實現這個接口的類決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行。
- 主要是針對同一產品等級(如海爾的冰箱,西門子的冰箱,美的的冰箱…z)。
2.2 適用場景
- 創建對象需要大量的重複代碼。
- 應用層不依賴於產品類實例如何被創建,實現等細節。
- 一個類通過子類來指定創建哪個對象。
2.3 模擬代碼
- 以錄製視頻爲例,現在有Java課程的視頻,Python的視頻,通過簡單工廠的方式將課程實例化。
- 抽象產品類Video
package com.fukexin.design.pattern.creational.factorymethod;
public abstract class Video {
public abstract void produce();
}
- 具體產品類JavaVideo
package com.fukexin.design.pattern.creational.factorymethod;
public class JavaVideo extends Video {
public void produce() {
System.out.println("錄製Java課程視頻");
}
}
- 具體產品類PythonVideo
package com.fukexin.design.pattern.creational.factorymethod;
public class PythonVideo extends Video {
public void produce() {
System.out.println("錄製Python課程視頻");
}
}
- 具體產品類FEVideo
package com.fukexin.design.pattern.creational.factorymethod;
public class FEVideo extends Video {
public void produce() {
System.out.println("錄製FE課程視頻");
}
}
- 抽象工廠類VideoFactory
package com.fukexin.design.pattern.creational.factorymethod;
public abstract class VideoFactory {
public abstract Video getInstance();
}
- 生產Java視頻的工廠類JavaVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;
public class JavaVideoFactory extends VideoFactory {
public Video getInstance() {
return new JavaVideo();
}
}
- 生產Python視頻的工廠類PythonVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;
public class PythonVideoFactory extends VideoFactory{
public Video getInstance() {
return new PythonVideo();
}
}
- 生產FE視頻的工廠類FEVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;
public class FEVideoFactory extends VideoFactory {
public Video getInstance() {
return new FEVideo();
}
}
- UML類圖
2.4 應用源碼解析
- java.util.Collection中的Iterator()可以看作爲一個工廠方法,它返回的Iterator即爲抽象產品,其中ArrayList中的Itr類實現Iterator接口,即爲實際產品。
public Iterator<E> iterator() {
return new ArrayList.Itr();
}
private class Itr implements Iterator<E>
3. 抽象工廠
3.1 定義
- 抽象工廠模式提供了一個創建一系列相關或相互依賴對象的接口。
3.2 適用場景
- 應用層不依賴於產品類實例如何被創建,實現等細節。
- 強調一系列相關的產品對象(屬於同一產品族,如美的的冰箱,美的的空調,美的的抽油煙機等)一起使用創建對象需要大量重複的代碼。
- 提供產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。
3.3 模擬代碼
- 場景:一個視頻不能稱作一個課程,現在要求課程必須有視頻,有手記。所以在Java這個產品族中使用抽象工廠模式。
- Video抽象類
package com.fukexin.design.pattern.creational.abstractfactory;
public abstract class Video {
public abstract void produce();
}
- JavaVideo具體類
package com.fukexin.design.pattern.creational.abstractfactory;
public class JavaVideo extends Video {
public void produce() {
System.out.println("錄製Java課程視頻");
}
}
- PythonVideo具體類
package com.fukexin.design.pattern.creational.abstractfactory;
public class PythonVideo extends Video {
public void produce() {
System.out.println("錄製Python課程視頻");
}
}
- Article抽象類
package com.fukexin.design.pattern.creational.abstractfactory;
public abstract class Article {
public abstract void produce();
}
- JavaArticle具體類
package com.fukexin.design.pattern.creational.abstractfactory;
public class JavaArticle extends Article {
public void produce() {
System.out.println("編寫Java課程手記");
}
}
- PythonArticle具體類
package com.fukexin.design.pattern.creational.abstractfactory;
public class PythonArticle extends Article {
public void produce() {
System.out.println("編寫Python課程手記");
}
}
- CourseFactory接口
package com.fukexin.design.pattern.creational.abstractfactory;
public interface CourseFactory {
public Video getVideo();
public Article getArticle();
}
- JavaCourseFactory工廠類
package com.fukexin.design.pattern.creational.abstractfactory;
public class JavaCourseFactory implements CourseFactory {
public Video getVideo() {
return new JavaVideo();
}
public Article getArticle() {
return new JavaArticle();
}
}
- PythonCourseFactory工廠類
package com.fukexin.design.pattern.creational.abstractfactory;
public class PythonCourseFactory implements CourseFactory {
public Video getVideo() {
return new PythonVideo();
}
public Article getArticle() {
return new PythonArticle();
}
}
- UML類圖
3.4 應用源碼解析
- java.util.Conection接口中對於一個同connection的createStatement()方法返回的Statement,createPrepareStatement()方法返回的PrepareStatement屬於同一產品族。
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String var1) throws SQLException;
- MyBatis中的SqlSesstionFactory中的openSession方法和getConfiguration()方法,其中openSession()方法返回的session也是一個接口(即抽象產品)。
SqlSession openSession(ExecutorType var1, Connection var2);
Configuration getConfiguration();
4. 比較
- 工廠方法和抽象工廠是對簡單工廠的延伸和拓展,工廠方法主要關注產品等級(西門子的冰箱,美的的冰箱,海爾的冰箱),而抽象工廠關注的是產品族(美的的空調,美的的冰箱,美的的抽油煙機)。