設計模式(四)—— 工廠模式
一、含義
工廠模式包含兩個方式:一個是抽象工廠模式,一個是工廠方法模式。
抽象工廠模式:提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類。
工廠方法模式:定義一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法讓類把例項化推遲到子類中。
二、要點
1.工廠模式都是用來封裝物件的建立。
2.工廠方法使用繼承:把物件的建立委託給子類,子類實現工廠方法來建立物件。
3.抽象工廠使用物件組合:物件的建立被實現在工廠介面所暴露出來的方法中。
4.工廠模式的作用是減少程式和具體類之間的依賴促進鬆耦合。
三、實戰分析工廠模式。
需求:對於一個厭倦了編碼的程式猿來說,回家開個餐廳是個不錯的選擇,賣漢堡就是一個不錯的選擇。
首先就是開一個漢堡店,由於漢堡的種類繁多,在漢堡店的例項中,我就需要更具型別來例項很多不同種類的漢堡,如下所示:
Hamburg orderHamburg(String type) { Hamburg hamburg; //例項具體的漢堡工作,隨著漢堡的不同,這裡的程式碼就需要修改 if (type.equals("beef")) { hamburg = new BeefHamburg(); } else if (type.equals("mutton")) { hamburg = new MuttonHamburg(); } else if (type.equals("bigMAC")) { hamburg = new BigMACHamburg(); } //這些步驟是通用的,不需要修改 hamburg.prepare(); hamburg.bake(); hamburg.box(); return hamburg }
所以直接在漢堡店中例項化漢堡,程式的耦合多太高,我們可以把建立漢堡的過程,給他抽離出來,單獨封裝成一個用來建立漢堡的例項類:
public class SimpleHamburgFactory { public Hamburg createHamburg(String type) { Hamburg hamburg; if (type.equals("beef")) { hamburg = new BeefHamburg(); } else if (type.equals("mutton")) { hamburg = new MuttonHamburg(); } else if (type.equals("bigMAC")) { hamburg = new BigMACHamburg(); } return hamburg; } }
這個時候漢堡店的設計就可如下:
public class HamburgStore {
//傳遞一個用來例項化漢堡實體的工廠
SimpleHamburgFactory simpleHamburgFactory;
public HamburgStore(SimpleHamburgFactory simpleHamburgFactory) {
this.simpleHamburgFactory = simpleHamburgFactory;
}
Hamburg orderHamburg(String type) {
Hamburg hamburg;
hamburg = simpleHamburgFactory.createHamburg(type);
hamburg.prepare();
hamburg.bake();
hamburg.box();
return hamburg
}
}
在你精心經營下,你的漢堡店越做越大,有很多加盟商想要加盟,加盟商根據所在地點的不同,可能生產的漢堡有所不同,我們的總店就相當於一個超類,別的加盟商就是需要實現這個超類,然後去自定義生產漢堡。總店的設計如下:
public abstract class HamburgStore {
public Hamburg orderHamburg(String type) {
hamburg = createHamburg(type);
hamburg.prepare();
hamburg.bake();
hamburg.box();
return hamburg;
}
//定義一個抽象方法,讓繼承的子類去實現用什麼工廠建立
abstract Hamburg createHamburg(String type);
}
所以工廠模式的型別可以如下去理解:
為什麼我們的漢堡可以買的這麼好呢?就是因為我們自己獨特的祕製配料,比如說麵粉,醬料等,隨著加盟商的增多,我們的配料也需要根據地方的不通,就行生產,這是使用我們就需要一個專門製作配料的工廠。
public interface HamburgIngredientFactory {
//每個原料都有一個對應的方法建立該原料
Dough createDough();
Sauce createSauce();
Cheese createCheese();
Pepperoni createPepperoni();
Clams createClam()s;
}
然後需要做的事就是為每個區域建造一個工廠,繼承至HamburgIngredientFactory,還需要提供一組原料類,來使用,最後將這些原料整合到HamburgStore中去。
public class SiChuangHamburgIngredientFactory implements HamburgIngredientFactory {
@Override
public Dough createDough() {
return new SiChuanDough();
}
@Override
public Sauce createSauce() {
return new SiChuanSauce();
}
@Override
public Cheese createCheese() {
return new SiChuanCheese();
}
@Override
public Pepperoni createPepperoni() {
return new SiChuanPepperoni();
}
@Override
public Clams createClam() {
return new SiChuanClams();
}
}
重新設計漢堡類
public abstract class Hamburg {
String name;
//這些都是漢堡需要用到的原料
Dough dough;
Sauce sauce;
Pepperoni pepperoni;
Clams clams;
//這個準備工作就是收集漢堡所需的原料,這些原料需要用工廠來實現
abstract void prepare();
void bake() {
System.out.println("Bake 20 minutes");
}
void box() {
System.out.println("hamburg put box");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
設計一個具體的類 :
public class CheeseHamburg extends Hamburg {
//需要一個原料工廠來提供原料
HamburgIngredientFactory hamburgIngredientFactory;
public CheeseHamburg(HamburgIngredientFactory hamburgIngredientFactory) {
this.hamburgIngredientFactory = hamburgIngredientFactory;
}
@Override
void prepare() {
dough = hamburgIngredientFactory.createDough();
sauce = hamburgIngredientFactory.createSauce();
clams = hamburgIngredientFactory.createClam();
}
}
從上訴程式碼中可以看出,所有抽象工廠的類圖,可以如下圖所示: