概述:
工廠模式可分爲3小類:
簡單工廠、工廠方法、抽象工廠
-
簡單工廠
直接上例子:
public class Test {
public static void main(String[] args) {
int code;
Duck duck;
if(code == 1){
duck = new DuckCall();
}else if(code == 2){
duck = new RubberDuck();
}else if(code == 3){
duck = new MallardDuck();
}else{
duck = new RedHeadDuck();
}
}
}
以上ifelse 的部分,會隨着鴨子的種類變化面臨增刪
也會隨着客戶需求在不同的code下創建另一種Duck
根據封裝變化
得到簡單工廠
class SimpleDuckFactory{
public Duck create(int code){
Duck duck;
if(code == 1){
duck = new DuckCall();
}else if(code == 2){
duck = new RubberDuck();
}else if(code == 3){
duck = new MallardDuck();
}else{
duck = new RedHeadDuck();
}
return duck;
}
}
這種將創建對象的代碼移動到另一個類中,稱作簡單工廠
優勢:
1》一個工廠被提取出來後,就可以“擺脫”原來的單個客戶,面向多個客戶
2》而且修改的時候,也只要修改這個簡單工廠類即可
-
工廠方法
上類圖(這次是Pizza店)
父類Pizza是一個abstract類,其中createPizza()是一個虛擬方法,需要子類實現
上代碼:
父類:
public abstract class PizzaStore {
Pizza order(){
int type = 0;
Pizza pizza = createPizza(type);
pizza.prepare();
return pizza;
}
abstract Pizza createPizza(int type);
}
子類:
public class NanjingPizzaStore extends PizzaStore{
Pizza createPizza(){
//這裏可以加入if else來進行擴展,如下第二個
return new NanjingPizza();
}
Pizza createPizza(int type){
Pizza pizza;
switch(type){
case 1:
//仔雞味
break;
case 2:
//咖喱味
break;
case 3:
//番茄味
break;
default:
//斷貨了
break;
}
return pizza;
}
}
給出定義:
定義了一個創建對象的接口,但是有子類決定具體實例化哪個類,工廠方法讓類把實例化操作推遲到子類
注意:
從上面的例子應該也可以看出,所謂的子類決定實例化哪一個Pizza,其實是通過父類的披薩店運行時選擇具體實現子類(例如:NanjingPizzaStore)來實現“動態”修改的效果。並不是子類在運行時決定,其實子類new哪個,是在代碼中寫死的(非動態)
-
抽象工廠
設計原則5:
理解:爲啥叫依賴倒置,拿本文中的例子來解釋,你要創建一個Pizza店,首先是自上而下的思路來創建你的類框架,現在採取倒置思維,自下而上思考,總結下層依賴抽象成接口,這樣就是“儘量多依賴抽象,少依賴具體類”啦
抽象工廠理解:簡單工廠+工廠方法的組合
上類圖:
首先用簡單工廠,將new的代碼從上層類中摳出來,並對這個“變化”部分進行抽象,這時候在採用工廠方法來實現這個框架的剩餘部分
上代碼(這裏以Pizza店爲例):
抽象出一個Pizza的接口:
public abstract class Pizza {
abstract String getDescription();
}
Pizza子類(雖然都是咖喱Pizza,但是上海的店和南京的店做出來的是口味不同的):
public class NanjingCurryPizza extends Pizza{
@Override
String getDescription() {
return "南京咖喱味Pizza";
}
}
public class ShanghaiCurryPizza extends Pizza{
@Override
String getDescription() {
return "上海咖喱味Pizza";
}
}
新建Pizza店:
public class PizzaStore {
final int chicken = 0x1;
final int curry = 0x2;
PizzaFactory factory;
//看到這裏依賴的並不是具體類,而是接口
public PizzaStore(PizzaFactory factory){
this.factory = factory;
}
Pizza order(int type){
if(type == chicken){
return factory.createChickenPizza();
}else if(type == curry){
return factory.createCurryPizza();
}else{
return null;
}
}
}
新建一個工廠抽象接口:
public interface PizzaFactory {
Pizza createChickenPizza();
Pizza createCurryPizza();
}
創建具體的南京&上海的Pizza工廠:
public class ShanghaiPizzaFactory implements PizzaFactory{
@Override
public Pizza createChickenPizza() {
return new ShanghaiChickenPizza();
}
@Override
public Pizza createCurryPizza() {
return new ShanghaiCurryPizza();
}
}
。。。南京就不列出了
理解:
從Pizza店摳出創建Pizza的代碼,對這個代碼抽象成一個PizzaFactory接口,然後用到工廠方法寫出具體的實現子類,有南京的PizzaFactory和上海的PizzaFactory
抽象工廠定義:
提供一個接口,用於創建相關或者依賴的對象的家族,而不需要明確指定具體類
與工廠方法的區別:
1》工廠方法是通過繼承來實現,而抽象工廠是通過組合
2》工廠方法用來創建一個產品,而抽象工廠則是用來創建一個產品家族
抽象工廠缺點:
1》一旦產品家族裏新增成員,就必須修改抽象接口了
抽象工廠優點:
1》將客戶與具體產品解耦,封裝變化利於維護
2》因爲客戶使用的是一個接口,我們方便給客戶替換產品家族
3》而切抽象工廠接口可以面對多個客戶,代碼複用