定義
定義一個用於創建對象的接口,讓子類決定實例化哪個類
使用場景
在任何需要生成複雜對象的地方,都可以使用工廠方法模式。複合對象適合使用工廠模式,用new就可以完成創建的對象無需使用工廠模式。
關鍵點
一個抽象工廠—定義創建對象的接口
抽象工廠的實現類—可以是一個實現或多個實現,用於生產需要的具體對象
一個抽象產品—工廠方法模式所創建的產品的父類
抽象產品的實現類—需要被創建的具體產品
實現
/**
* 抽象工廠類—定義生產抽象對象的接口
*/
public abstract class AbstractFactory {
public abstract AbstractProduct createProduct();
}
/**
* 抽象產品類—工廠模式的抽象接口需要創建返回的類型
*/
public abstract class AbstractProduct {
/**
* 抽象產品內的抽象方法
*/
public abstract void showProductName();
}
/**
* 抽象工廠的實現類—創建具體需要的產品
*/
public class ProductFactory extends AbstractFactory {
@Override
public AbstractProduct createProduct() {
//根據需要創建具體的產品,這裏我們創建產品A
return new ProductA();
}
}
/**
* 具體的產品A
*/
public class ProductA extends AbstractProduct {
@Override
public void showProductName() {
Log.i("Product:", "A");
}
}
/**
* 具體的產品B
*/
public class ProductB extends AbstractProduct {
@Override
public void showProductName() {
Log.i("Product:", "B");
}
}
使用
AbstractFactory factory = new ProductFactory();
AbstractProduct product = factory.createProduct();
product.showProductName();
輸出
01-01 00:05:58.728 2840-2840/com.example.admin.singleinstancedemo I/Product:: A
當然我們也可以在具體創建產品的工廠類裏面創建B產品。上面這種方式是最常見的需要哪一個產品就生產哪一個。除此之外,我們還可以利用反射的方式去更加簡潔的生產具體的產品對象,修改抽象工廠類和具體工廠類如下:
/**
* 抽象接口類—定義生產抽象對象的接口
*/
public abstract class AbstractFactory {
public abstract <T extends AbstractProduct> T createProduct(Class<T> clz);
}
/**
* 抽象工廠的實現類—創建具體需要的產品
*/
public class ProductFactory extends AbstractFactory {
@Override
public <T extends AbstractProduct> T createProduct(Class<T> clz) {
AbstractProduct product = null;
try {
product = (AbstractProduct) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) product;
}
}
使用
AbstractFactory factory = new ProductFactory();
AbstractProduct product = factory.createProduct(ProductB.class);
product.showProductName();
輸出結果
01-01 00:26:19.950 16938-16938/com.example.admin.singleinstancedemo I/Product:: B
需要哪一個類的對象就傳入哪一個類的類型即可,這種方式比較簡介、動態,當然我們也可以爲每個具體的產品定義一個具體的工廠類,比如在第一種方式基礎上多增加一個專門用於生產ProductB的工廠
/**
* 抽象工廠的實現類—創建具體需要的產品B
*/
public class ProductFactoryB extends AbstractFactory {
@Override
public AbstractProduct createProduct() {
return new ProductB();
}
}
然後需要A的時候使用ProductFactory工廠創建A實例,需要B的時候使用ProductFactoryB工廠創建B實例,各司其職。這樣擁有多個工廠的方式我們稱爲多工廠方法模式。
當只有一個工廠的時候,我們還是爲工廠提供了一個抽象類,是否可以將其簡化掉呢?當然是可以的:
/**
* 直接提供靜態方法—向外創建對象
*/
public class ProductFactory {
public static AbstractProduct createProduct(){
return new ProductA();
}
}
像這樣的方式又稱之爲簡單工廠模式或靜態工廠模式
小結
工廠方法模式降低了對象之間的耦合度,依賴於抽象的架構,將實例化的任務交由子類去完成,有非常好的擴展性,符合軟件設計原則。
優點:
1.在工廠方法中,用戶只需要知道所要產品的具體工廠,無須關係具體的創建過程,甚至不需要具體產品類的類名。
2.在系統增加新的產品時,我們只需要添加一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。
缺點:
1.每次增加一個產品時,都需要增加一個具體類和對象實現工廠,是的系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。