1. 程式人生 > >簡單工廠、工廠方法和抽象工廠的區別

簡單工廠、工廠方法和抽象工廠的區別

工廠模式一般分為簡單工廠、工廠方法和抽象工廠三種,看了很多資料,好多講的都是雲裡霧裡的。要麼是概念太多,讓人看得一臉懵逼,要麼是舉得例子不太恰當,看了更讓人迷惑了。經過自己一番研究,通過一個簡單的例子,終於搞明白了它們之間的區別。

下面以生產寶馬、賓士汽車的工廠為例,講解它們之間的區別。

一、簡單工廠模式

建立一個工廠類,根據傳入的引數來決定建立哪個汽車類

//汽車介面
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();  //低配賓士車
    }
}

乍一看,抽象工廠和工廠方法特別的相似,其實這裡邊就是多了一個產品族的概念,它強調一個產品族的物件應該放到同一個工廠類裡邊。比如,我再需要一箇中配版或者豪華版的汽車製造商,只需要實現它的具體工廠類和相應的各同等級的汽車類。

總結:

  1. 簡單工廠顧明思議,實現比較簡單,只需要傳入一個特定引數即可,不用知道具體的工廠實現類名,缺點就是違背了開閉原則。
  2. 工廠方法和抽象工廠,遵守開閉原則,解耦了類關係。但是,擴充套件比較複雜,需要增加一系列的類。
  3. 需要注意,工廠方法和抽象工廠的區別就在於,抽象工廠關注於某一個產品族,當產品物件之間是有關聯關係的一個產品族時用這種方式,而工廠方法沒有產品族的概念。