1. 程式人生 > >建立型設計模式之工廠方法模式

建立型設計模式之工廠方法模式

工廠方法模式的介紹

工廠方法模式是一種結構簡單的模式,並且在我們的應用中很廣泛,如Android中Activity的各個生命週期的回撥,以onCreate方法為例,它就可以看做是一個工廠方法,我們在其中構造我們的View並返回給framework處理。

工廠方法模式的定義

定義一個用於建立物件的介面,讓子類決定例項化哪個類。

工廠方法模式的使用場景

在任何需要生成複雜物件的地方,都可以使用工廠方法模式。複雜物件適合使用工廠方法模式,用new就能完成建立的物件無需使用工廠方法模式。

工廠方法模式的類圖

角色介紹:

Factory - 抽象工廠,是工廠方法的核心

ConcreteFactory - 具體工廠,實現了業務邏輯

Product - 抽象產品,是工廠方法模式所建立的產品的父類

ConcreteProduct - 為實現抽象產品的某個具體產品

抽象工廠的簡單實現

下面生產汽車為例,要生產三款汽車,於是使用一條生產線來生產,我們先定義產品,產品是汽車。

抽象汽車,即抽象產品

public abstract class Car {
    public abstract void drive();
}

接下來是具體的車型

奧迪汽車,即具體的產品類

public class AudiCar extends Car {
    @Override
    public void drive() {
        System.out.println("奧迪汽車開始啟動啦!");
    }
}

賓士汽車,即具體的產品類

public class BenzCar extends Car {

    @Override
    public void drive() {
        System.out.println("賓士車開始啟動啦!");
    }
}

寶馬汽車,即具體的產品類

public class BWMCar extends Car {
    @Override
    public void drive() {
       System.out.println("寶馬汽車開始啟動啦!");
    }
}

有了產品就要有工廠來生產,定義一個汽車抽象工廠。

抽象汽車工廠,即抽象工廠角色

public abstract class CarFactory {
    public abstract Car createCar();
}

接下來是具體的車型工廠。

生產奧迪車的工廠,即具體工廠類

public class AudiCarFactory extends CarFactory {

    @Override
    public Car createCar() {
        return new AudiCar();
    }

}

生產賓士車的工廠,即具體工廠類

public class BenzCarFactory extends CarFactory {
    @Override
    public Car createCar() {
        return new BenzCar();
    }
}

生產寶馬車的工廠,即具體工廠類

public class BWMCarFactory extends CarFactory {
    @Override
    public Car createCar() {
        return new BWMCar();
    }
}

最後我們將各個汽車的生產組裝成一條生產線。

客戶端

public class Client {

    public static void main(String[] args){
        //製造各個工廠
        CarFactory audiFactory = new AudiCarFactory();
        CarFactory benzFactory = new BenzCarFactory();
        CarFactory bwmFactory = new BWMCarFactory();
        //生產各種車
        Car audiCar = audiFactory.createCar();
        Car benzCar = benzFactory.createCar();
        Car bwmCar = bwmFactory.createCar();
        //車啟動
        audiCar.drive();
        benzCar.drive();
        bwmCar.drive();
    }

}

輸出結果

奧迪汽車開始啟動啦!
賓士車開始啟動啦!
寶馬汽車開始啟動啦!

可以看到我們需要哪種車型就可以定義哪種車型的具體工廠,像這樣擁有多個工廠的的方式我們稱之為多工廠模式,每個工廠各司其職。

但上面的方式不好的是會產生大量工廠,使程式碼臃腫,在實際開發中,我們可以使用反射的方式更加簡潔的來生產具體的產品物件,此時需要在工廠方法的引數列表中傳入一個Class類來決定是哪一個產品類。

使用反射的方式來生產具體的產品物件,抽象工廠角色

public abstract class CarFactory2 {

    /**
     * 抽象工廠方法,具體生產什麼產品由子類決定
     */
    public abstract <T extends Car> T createCar(Class<T> car);

}

對於 具體的工廠,則通過反射獲取類的例項即可

public class ConcreteCarFactory extends CarFactory2 {
    
    @Override
    public <T extends Car> T createCar(Class<T> car) {
        Car c = null;
        try {
            c = (T) Class.forName(car.getName()).newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) c;
    }
    
}

客戶端

public class Client {

    public static void main(String[] args){
        //建立工廠
        CarFactory2 carFactory = new ConcreteCarFactory2();
        //生產車
        AudiCar audiCar = carFactory.createCar(AudiCar.class);
        BenzCar benzCar = carFactory.createCar(BenzCar.class);
        BWMCar bwmCar = carFactory.createCar(BWMCar.class);
        //車啟動
        audiCar.drive();
        benzCar.drive();
        bwmCar.drive();
    }
}

輸出和和上面一樣 

以上的方式,需要哪一個產品的物件,就傳入哪一個產品的類的型即可,這種方式比較簡潔,動態。

上面我們有三個工廠,如果我們只需要生產一種車型,即我們只有一個工廠時,我們就可以把抽象工廠簡化掉,將對應的工廠方法改為靜態方法,像下面,我們只生產一輛五菱車。

一個工廠,只生產一種產品

public class Factory {
    
    public static Car createWuLingCar(){
        return new WuLingCar();
    }
    
}

像這樣的方式又稱為簡單工廠方式或靜態工廠方式,它是工廠方式模式的一個弱化版本。

總結

工廠模式依賴於抽象的架構,將例項化的具體任務交給子類去完成,有非常好的擴充套件性。

優點:

將類的例項化邏輯交由工廠實現,實現程式碼模組之間的解耦

缺點:

每次為工廠模式新增新的產品時都要編寫一個新的產品類,同時還要引入抽象層,回導致類結構的複雜