工廠方法模式
認識
- 工廠方法的主要功能是讓父類在不知道具體實現的情況下,完成自身的功能調用,而具體的實現延遲到子類來實現.
- 工廠方法模式通常是針對Product接口的每個實現類都提供一個與之對應的Factory實現類用於創建該對象,這樣能夠實現更好的擴展性。
- 也可以把父類實現爲一個具體的類,同時在父類中提供獲取所需對象的默認實現方法,這樣就算沒有具體的子類去創建對象,也能夠完成功能運行。
思考
- 工廠方法的本質:工廠是抽象的,只定義需要的對象,所需對象的創建延遲到工廠的子類中實現
- 相比於簡單工廠和抽象工廠,有更好的擴展性,當增加一個Product的實現類時,只需要添加一個Factory與之對應的實現類就行。
- 工廠方法模式中工廠實現類一次方法只操作一個接口返回值,抽象工廠模式操作的是多個接口
優缺點
- 可以在不知道具體實現的情況下編程,解耦合。
- 更容易擴展對象的新版本,當有一個新的對象需要創建的時候創建一個新的工廠實現類返回新的對象。
- 缺點是每個Product的實現都需要創建一個Factory的實現,增加了客戶端調用的選擇難度。
使用場景
- 工廠方法模式作爲一種創建類模式,在任何需要生成複雜對象的地方,都可以使用工廠方法模式,比靜態工廠模式更好的擴展。
- 工廠方法模式將具體的操作延遲到子類實現,當父類不做任何操作,將具體操作通過抽象方法延遲到子類去實現的時候可以使用。
- 當父類的操作需要一個對象的時候,提供抽象方法,讓子類實現抽象方法創建需要的對象,同時在父類中定義使用該對象的公共方法,實現依賴倒置。
UML圖
封裝Product實現類的具體細節,創建一個抽象工廠,爲每個Product接口的實現類都創建一個工廠實現類,在抽象方法中創建對應的Product的實現類對象。之後如果擴展Product的實現類,只需要擴展一個對象的工廠實現類就行。
客戶端操作工廠方法的過程
代碼實現
/**
* 產品接口
*/
public interface IProduct {
public void operation();
}
/**
* 產品實現類A
*/
public class ConcreateProductA implements IProduct {
public void operation() {
System.out.println("創建產品A");
}
}
/**
* 產品實現類B
*/
public class ConcreateProductB implements IProduct {
public void operation() {
System.out.println("創建產品B");
}
}
/**
* 抽象工廠類
*
*/
public abstract class Factory {
/**
* 定義抽象,具體實現延遲到子類中實現
*/
protected abstract IProduct getProduct();
/**
* 提供方法供客戶端調用
*/
public IProduct createProduct() {
// 進行操作
IProduct product = this.getProduct();
// 進行操作
return product;
}
}
/**
* 工廠實現類A
*/
public class ConcreateFacotryA extends Factory {
/**
* 實現類中創建對應的product的子類返回
*/
@Override
protected IProduct getProduct() {
return new ConcreateProductA();
}
}
/**
* 工廠實現類B
*/
public class ConcreateFacotryB extends Factory {
/**
* 實現類中創建對應的product的子類返回
*/
@Override
protected IProduct getProduct() {
return new ConcreateProductB();
}
}
/**
* 客戶端調用
*/
public class Client {
public static void main(String[] args) {
// 客戶端調用 Factory的 ConcreateFacotryA 實現類創建對象
Factory factoryA = new ConcreateFacotryA();
IProduct productA = factoryA.createProduct();
productA.operation();
// 客戶端調用 Factory的 ConcreateFacotryB 實現類創建對象
Factory factoryB = new ConcreateFacotryB();
IProduct productB = factoryB.createProduct();
productB.operation();
}
}
通過工廠方法模式實現依賴倒置,父類(接口)無法new實例,只定義操作,而操作中所需要的外部對象,由子類實現抽象方法去創建,將對象的創建延遲到子類中,能夠實現更好的擴展。同時實現依賴倒置和延遲加載。
public abstract class A1 {
/**
* 工廠方法,創建C1,類似於從子類注入進來的途徑
* @return C1的對象實例
*/
protected abstract C1 createC1();
public void t1(){
//這裏需要使用C1,可是不知道究竟是用哪一個,也就不主動去創建C1了,怎麼辦?
//反正會在子類裏面實現,這樣更省心,這裏不用管怎麼獲取C1,直接使用就好了
createC1().tc();
}
}
public class A {
/**
* 等待被注入進來
*/
private C c = null;
/**
* 注入資源C的方法
* @param c 被注入的資源
*/
public void setC(C c){
this.c = c;
}
public void t1(){
//這裏需要使用C類,可是又不讓主動去創建C了,怎麼辦?
//反正就要求從外部注入,這樣更省心,
//自己不用管怎麼獲取C,直接使用就好了
c.tc();
}
}
public class A2 extends A1 {
protected C1 createC1() {
//真正的選擇具體實現,並創建對象
return new C2();
}
}