考慮一個場景:
某公司需要使用文件導出系統將某些數據打包到服務器上,但是現在還不知道打包的方式和文件的類型。
也即只知道有導出這樣一個接口,但不知道具體實現。
客戶端只需要調用抽象的接口對象中的方法,而不用關心具體實現。
定義:
定義一個用於創建對象的接口,讓子類決定實例化哪一個類,工廠方法模式使一個類的實例化延遲到其子類。
角色:
Product:
定義工廠方法所創建的對象的接口,也就是實際需要使用的對象的接口
package com.kris.study;
public interface Product {
//可以定義屬性和方法
public void doSomething();
}
ConcreteProduct:
具體Product對象
package com.kris.study;
public class ConcreteProduct implements Product{
@Override
public void doSomething() {
System.out.println("生產商品");
}
}
Creator:
創建器,聲明工廠方法,工廠方法通常會返回一個Product類型的實例對象,而且多是抽象方法.也可以在Creator裏面提供
工廠方法的默認實現,讓工廠方法返回一個缺省的Product類型的實例對象
package com.kris.study;
public abstract class Creator {
protected abstract Product factoryMethod();
public void someOperation(){
Product product = factoryMethod();
product.doSomething();
}
}
ConcreteCreator:
具體創建的對象,覆蓋實現Creator定義的工廠方法,返回具體的Product實例
package com.kris.study;
public class ConcreteCreator extends Creator {
@Override
protected Product factoryMethod() {
return new ConcreteProduct();
}
}
客戶端調用:
可以使用new新建具體的Creator子類也可以傳入參數由父類決定使用哪一個子類就像簡單工廠.
package com.kris.study;
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
creator.someOperation();
}
}
原理分析:
工廠方法模式的主要功能是讓父類不知道具體實現的情況下,完成自身的功能調用; 而具體的實現延遲到子類。
也就是在工廠方法的父類中會有使用這些產品對象來實現一定功能的方法,而這些產品對象是由子類來提供.
工廠方法模式與IoC/DI
IoC:控制反轉
DI:依賴注入
1)參與者
一般有三個參與者,一個是某個對象,另一個是IoC/DI容器,還有一個是某個對象的外部資源
2)誰依賴於誰
某個對象依賴於IoC/DI容器
3)爲什麼需要依賴
對象需要容器提供某個對象需要的外部資源
4)誰注入誰
容器注入某個對象
5)注入什麼
注入某個對象需要的外部資源
6)誰控制誰
容器控制某個對象
7)控制什麼
控制對象實例的創建
依賴注入是以應用程序的角度去看,應用程序依賴於容器創建並注入他所需要的外部資源
控制反轉是以容器的角度去看,容器控制應用程序,由容器反向的嚮應用程序注入需要的外部資源
工廠方法模式和IoC/DI在思想上非常相似,都是主動變被動。
參數化工廠方法:通過給工廠方法傳遞參數,讓工廠方法根據參數的不同來創建不同的產品對象。這時候工廠父類會有
一個默認的實現。
工廠方法模式優點:
在不知具體實現下實現功能方法,更容易擴展,連接平行的類層次結構.
缺點:
增加了具體產品對象與工廠方法的耦合性
本質:延遲到子類來選擇實現
與簡單工廠的不同:
簡單工廠是在工廠類裏面直接進行選擇實現。
工廠方法會把這個具體實現的工作延遲到子類進行.工廠類裏面的使用工廠方法的地方是依賴於抽象而不是具體的實現。
何時使用工廠方法
①一個類需要創建某個接口的對象,但是又不知道具體的實現.
②一個類希望由它的子類來創建某個方法需要的對象.