工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。這樣在簡單工廠模式裏集中在工廠方法上的壓力可以由工廠方法模式裏不同的工廠子類來分擔,程序大大提高了靈活性——當有新的產品時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,而不必去修改任何已有的代碼,程序提高了擴展性,同時也符合”開閉原則“。
沿用簡單工廠方法模式中的例子,隨着《中餐廳》的火爆之泰國程度,顧客量越來越大,從起初的湘菜、川菜、東北菜逐次擴至粵菜、香港菜,爲了滿足“開閉原則”,減少菜品和工廠的耦合度,採用工廠方法模式對《中餐廳》進行了改良。
package com.pattern.factory.pub;
public interface Food {
public void cooking(String foodName);
}
package com.pattern.factory.pub;
public class HuNanFood implements Food {
public void cooking(String foodName) {
System.out.println("【"+foodName+"】上來咯!");
}
}
package com.pattern.factory.pub;
public class SiChuanFood implements Food {
@Override
public void cooking(String foodName) {
System.out.println("【"+foodName+"】上來咯!");
}
}
package com.pattern.factory.pub;
public class DongBeiFood implements Food {
@Override
public void cooking(String foodName) {
System.out.println("【"+foodName+"】上來咯!");
}
}
抽象出工廠的統一接口,每一種菜系定義一類工廠,分別去與“接口”對接,不同的菜系分別用不同的工廠生產,這樣即使工廠A出了問題,不會影響工廠B,減少風險的發生以及提高可擴展性。 package com.pattern.factory.method;
import com.pattern.factory.pub.Food;
public interface FoodFactory {
public Food createFood(String foodName);
}
package com.pattern.factory.method;
import com.pattern.factory.pub.Food;
import com.pattern.factory.pub.HuNanFood;
public class HuNanFoodFactory implements FoodFactory {
public Food createFood(String foodName) {
HuNanFood food=new HuNanFood();
food.cooking(foodName);
return food;
}
}
package com.pattern.factory.method;
import com.pattern.factory.pub.Food;
import com.pattern.factory.pub.SiChuanFood;
public class SiChuanFoodFactory implements FoodFactory{
public Food createFood(String foodName) {
SiChuanFood food=new SiChuanFood();
food.cooking(foodName);
return food;
}
}
package com.pattern.factory.method;
import com.pattern.factory.pub.DongBeiFood;
import com.pattern.factory.pub.Food;
public class DongBeiFoodFactory implements FoodFactory {
public Food createFood(String foodName) {
DongBeiFood food=new DongBeiFood();
food.cooking(foodName);
return food;
}
}
烏拉拉,來客人啦,來一個剁椒魚頭、筍尖臘肉、豬肉粉條。。。
import com.pattern.factory.method.FoodFactory;
import com.pattern.factory.method.HuNanFoodFactory;
import com.pattern.factory.method.SiChuanFoodFactory;
public class Test {
public static void main(String[] args){
//第一個菜:剁椒魚頭
FoodFactory f1=new HuNanFoodFactory();
f1.createFood("剁椒魚頭");
//第二個菜:筍尖臘肉
FoodFactory f2=new SiChuanFoodFactory();
f2.createFood("筍尖臘肉");
//第三個菜:豬肉粉條
FoodFactory f3=new DongBeiFoodFactory();
f3.createFood("豬肉粉條");
}
}
通過工廠方法模式的例子可以看到,工廠方法模式有四個要素:
- 工廠接口:工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。在實際編程中,有時候也會使用一個抽象類來作爲與調用者交互的接口,其本質上是一樣的。
- 工廠實現:工廠實現決定如何實例化產品,是實現擴展的途徑,需要有多少種產品,就需要有多少個具體的工廠實現。
- 產品接口:產品接口的主要目的是定義產品的規範,所有的產品實現都必須遵循產品接口定義的規範。產品接口是調用者最爲關心的,產品接口定義的優劣直接決定了調用者代碼的穩定性。同樣,產品接口也可以用抽象類來代替,但要注意最好不要違反里氏替換原則。
- 產品實現:實現產品接口的具體類,決定了產品在客戶端中的具體行爲。
優點:克服了簡單工廠模式違背開放-封閉原則的缺點,降低客戶端和工廠的耦合性,提高了程序的可擴展性。
缺點:每增加一個產品,相應的也要增加一個子工廠,加大了額外的開發量。