之前討論了簡單工廠模式,回顧一下它的弊端,主要有3個:①當新增一種產品時,需要修改工廠類中的方法,違反了開閉原則。②當產品類非常多的時候,工廠類中的判斷邏輯也會變得複雜,不利於維護。③衆多客戶端都依賴同一個工廠類,當該工廠類無法工作時,調用它的客戶端也無法工作。
爲了解決上面提到的弊端,我們需要用到工廠方法模式來作爲替代方案。工廠方法模式是簡單工廠模式的進一步抽象。
工廠方法模式描述
定義
工廠方法模式是簡單工廠模式的進一步抽象化和推廣,工廠方法模式裏不再只由一個工廠類決定那一個產品類應當被實例化,這個決定被交給抽象工廠的子類去做。
角色組成
- 1)抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
- 2)具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。
- 3)抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
- 4)具體產品角色。
類圖構成
工廠方法模式VS簡單工廠模式
回到之前的討論,使用了工廠方法模式之後,當新增一種產品時,我們需要做什麼?
- 新增一個產品的實現類ProductC。
- 新增一個具體工廠類。
- 在客戶端調用。
如此來看,我們不必修改任何已有的代碼,完全符合開閉原則。
工廠方法模式實現代碼
產品接口
public interface Product extends Serializable {
void show();
}
產品實現
public class ProductA implements Product {
private static final long serialVersionUID = 1891930199408654755L;
public void show() {
System.out.println("This is A");
}
}
public class ProductB implements Product {
private static final long serialVersionUID = 7748930858331328998L;
public void show() {
System.out.println("This is B");
}
}
工廠接口
public interface Factory {
Product createProduct();
}
工廠實現類
public class ProductAFactory implements Factory {
public Product createProduct() {
return new ProductA();
}
}
public class ProductBFactory implements Factory {
public Product createProduct() {
return new ProductB();
}
}
客戶端調用
public class FactoryClient {
public static void main(String[] args) {
Factory factory = new ProductAFactory();
Product product = factory.createProduct();
product.show(); // This is A
factory = new ProductBFactory();
product = factory.createProduct();
product.show(); // This is B
}
}
工廠方法模式存在的弊端
根據上面的邏輯,每新增一種產品,我們就要新增一個產品實現類,新增一個產品工廠實現類。當系統中有數百種產品的話,就要有對應多的工廠類,對於維護是個挑戰。
工廠方法模式適用場景
其實也是所有工廠模式的適用場景。
- ①作爲一種創建類模式,在任何需要生成複雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只需要通過new就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。
- ②工廠模式是一種典型的解耦模式,迪米特法則在工廠模式中表現的尤爲明顯。假如調用者自己組裝產品需要增加依賴關係時,可以考慮使用工廠模式。將會大大降低對象之間的耦合度。
- ③由於工廠模式是依靠抽象架構的,它把實例化產品的任務交由實現類完成,擴展性比較好。也就是說,當需要系統有比較好的擴展性時,可以考慮工廠模式,不同的產品用不同的實現工廠來組裝。