簡單工廠、工廠方法和抽象工廠的區別
工廠模式一般分為簡單工廠、工廠方法和抽象工廠三種,看了很多資料,好多講的都是雲裡霧裡的。要麼是概念太多,讓人看得一臉懵逼,要麼是舉得例子不太恰當,看了更讓人迷惑了。經過自己一番研究,通過一個簡單的例子,終於搞明白了它們之間的區別。
下面以生產寶馬、賓士汽車的工廠為例,講解它們之間的區別。
一、簡單工廠模式
建立一個工廠類,根據傳入的引數來決定建立哪個汽車類
//汽車介面 public interface Car { void getCar(); } //寶馬汽車類 public class BMWCar implements Car { @Override public void getCar() { System.out.println("這是寶馬車"); } } //賓士汽車類 public class BenzCar implements Car { @Override public void getCar() { System.out.println("這是賓士車"); } } //工廠類,用於決定建立哪一個具體的汽車類 public class DefaultFactory { public Car produce(String name){ if(name.equals("benz")){ return new BenzCar(); }else if(name.equals("bmw")){ return new BMWCar(); } return null; } } public class FTest { public static void main(String[] args) { DefaultFactory factory = new DefaultFactory(); Car car = factory.produce("bmw"); car.getCar(); //這是寶馬車 Car benz = factory.produce("benz"); benz.getCar(); //這是賓士車 } }
可以看到,在具體的工廠類DefaultFactory中,我們根據傳入的name來決定建立哪一個汽車類。當需要建立寶馬時,傳入bmw,當需要建立賓士時傳入benz。思考一下,如果我需要建立一個大眾汽車呢。是不是需要建立一個大眾汽車類實現Car介面,還需要修改工廠類的produce方法,新增一個大眾的分支。 再回憶一下,之前講過的軟體六大設計原則之一開閉原則。很明顯,這違背了開閉原則(對修改是關閉的)。
於是,有了下邊的工廠方法,可以保證遵循開閉原則。
二、工廠方法模式
工廠方法,相比於簡單工廠,多了一個角色——工廠介面,負責定義生產汽車的公共介面,然後每個工廠實現類都去實現這個介面。
//工廠介面 public interface IFactory { Car produce(); } //寶馬生產工廠 public class BMWFactory implements IFactory{ @Override public Car produce() { return new BMWCar(); } } //賓士生產工廠 public class BenzFactory implements IFactory { @Override public Car produce() { return new BenzCar(); } } public class FacTest { public static void main(String[] args) { BMWFactory bmwFactory = new BMWFactory(); bmwFactory.produce().getCar(); //這是寶馬車 BenzFactory benzFactory = new BenzFactory(); benzFactory.produce().getCar(); //這是賓士車 } }
可以看到,我把之前的一個工廠,拆分為兩個工廠。當具體需要哪個汽車的時候,就去例項化它對應的工廠。這樣,當再需要大眾車的時候,我只需要新增一個大眾車的類和大眾車對應的工廠實現類去實現IFactory介面就可以了。不需要修改原來的程式碼,這就符合開閉原則了。
三、 抽象工廠模式
初識抽象工廠的同學,總是很迷惑它和工廠方法有什麼區別,不就是在工廠實現類裡多了幾個方法嗎。其實,抽象工廠是對工廠方法的升級,用於建立一組相互關聯或相互依賴的物件。
在此需要了解一下產品等級和產品族的關係。假如有一個汽車製造商,它只生產低配版的汽車產品(至於為什麼,我猜是低配版更親民,銷量更高吧,哈哈),其中就包括低配寶馬和低配賓士。還有一個汽車製造商只生產高配版的汽車(沒什麼原因,就是錢多任性,高階大氣上檔次),如高配寶馬和高配賓士。
我們就把高配製造商或者低配製造商稱為一個產品族。而其中的低配寶馬和低配賓士屬於同一個產品等級,高配寶馬和高配賓士屬於同一個產品等級。
畫一張圖來理解一下它們的概念,橫向是三個產品族,縱向是兩個產品等級。
程式碼如下:
//工廠介面,包含兩個方法,建立寶馬和建立賓士
public interface IFactory {
Car produceBMW();
Car produceBenz();
}
//-------- 高配車和工廠實現類 -------//
public class HighBMW implements Car {
@Override
public void getCar() {
System.out.println("高配寶馬車");
}
}
public class HighBenz implements Car {
@Override
public void getCar() {
System.out.println("高配賓士車");
}
}
public class HighFactory implements IFactory {
@Override
public Car produceBMW() {
return new HighBMW();
}
@Override
public Car produceBenz() {
return new HighBenz();
}
}
//-------- 低配車和工廠實現類 ----------//
public class LowBMW implements Car {
@Override
public void getCar() {
System.out.println("低配寶馬車");
}
}
public class LowBenz implements Car {
@Override
public void getCar() {
System.out.printf("低配賓士車");
}
}
public class LowFactory implements IFactory {
@Override
public Car produceBMW() {
return new LowBMW();
}
@Override
public Car produceBenz() {
return new LowBenz();
}
}
public class AbsTest {
public static void main(String[] args) {
HighFactory highFactory = new HighFactory();
highFactory.produceBMW().getCar(); //高配寶馬車
highFactory.produceBenz().getCar(); //高配賓士車
LowFactory lowFactory = new LowFactory();
lowFactory.produceBMW().getCar(); //低配寶馬車
lowFactory.produceBenz().getCar(); //低配賓士車
}
}
乍一看,抽象工廠和工廠方法特別的相似,其實這裡邊就是多了一個產品族的概念,它強調一個產品族的物件應該放到同一個工廠類裡邊。比如,我再需要一箇中配版或者豪華版的汽車製造商,只需要實現它的具體工廠類和相應的各同等級的汽車類。
總結:
- 簡單工廠顧明思議,實現比較簡單,只需要傳入一個特定引數即可,不用知道具體的工廠實現類名,缺點就是違背了開閉原則。
- 工廠方法和抽象工廠,遵守開閉原則,解耦了類關係。但是,擴充套件比較複雜,需要增加一系列的類。
- 需要注意,工廠方法和抽象工廠的區別就在於,抽象工廠關注於某一個產品族,當產品物件之間是有關聯關係的一個產品族時用這種方式,而工廠方法沒有產品族的概念。