工廠模式是java中最常用的設計模式之一。它提供了一種創建對象的最佳方式,屬於創建型模式。
先舉一個形象店的例子來簡單理解一下工廠模式。假如你去一家飯店吃飯,飯店有一名服務員,這家飯店提供不同種類和不同菜系的飯菜,你根據菜單點你想要的飯菜,並通知服務員,但你並不需要了解這些飯菜是如何做出來的,服務員根據你的需要決定需要做哪些菜。
在此情境下,飯店就相當於是一個工廠,服務員就相當於是這個工廠對外提供的公共接口,而每一道菜就相當於一個工廠類,而你去飯店點餐就相當於客戶在不同條件下有計劃的要求創建實例。
OK,我們可以從以上情景中看出,工廠模式的核心就是把創建實例的過程放到子類執行。
接下來我們以形狀類爲例建立類圖:
接下來我們將逐步實現這個類圖。
第一步:創建Shape接口
public interface Shape{
void draw(); //接口中聲明一個draw()方法
}
第二步:創建Shape的實現類(實體類)
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method."); //重寫Shape接口中的draw()方法
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
每一個實體類中都重寫了(必須重寫)接口Shape中的draw(),並打印一句話作爲區分。
至此我們類圖的左半部分就完成了,下面開始創建工廠類。
第三步:創建工廠,生成基於給定信息的實體類對象
public class ShapeFactory {
//使用 getShape 方法獲取形狀類型的對象
public Shape getShape(String shapeType){ //此函數由主函數調用,參數爲用戶想要得到的形狀名稱
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){ //這裏驗證傳入的類型信息時忽略了大小寫,爲客戶端的傳輸提供了容錯空間
return new Circle();
}
else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
從代碼實現不難看出,工廠類ShapeFactory中的getShape方法完成創建實例的操作,是根據用戶傳入的期望值創建對應的實例,並將創建的實例返回。但對客戶端來說,客戶端並不需要知道創建實例的具體過程,只需要得到想要的結果就行了。
第四步:使用該工廠類,通過傳遞類型信息來獲取實體類的對象
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory(); // 首先需要創建工廠類的對象
//獲取 Circle 的對象,並調用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//調用 Circle 的 draw 方法
shape1.draw();
//獲取 Rectangle 的對象,並調用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//調用 Rectangle 的 draw 方法
shape2.draw();
//獲取 Square 的對象,並調用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//調用 Square 的 draw 方法
shape3.draw();
}
}
由以上代碼可以看出,客戶端需要創建工廠類的對象以調用工廠類中的方法,進而創建實體類的對象。另外,客戶端還需要知道要創建的對象的類型,在這裏也就是Shape,用它來聲明引用用來接收工廠類返回的對象。
最後我們來驗證一下輸出結果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
以上結果證明客戶端成功地通過傳入不同的類型信息獲得了對應的實體類對象。
OK,以上就是工廠模式的實現過程,接下來我們簡要總結一下工廠模式。
工廠模式通過定義創建對象的接口,這個接口面向工廠類,根據工廠類的方法調用決定實例化哪一個實體類。簡單來說就是把創建對象放在子類執行。
工廠模式主要有以下幾個優點:
1、用戶只要知道想要實例化的類名就可以創建這個類的實例了。
2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以,降低了工廠類與客戶端的耦合。
3、屏蔽產品的具體實現,調用者只關心產品的接口。
工廠模式的缺點主要表現在,每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。
注意事項:作爲一種創建型模式,在任何需要生成複雜對象的地方,都可以使用工廠模式。有一點需要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。