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

建立型設計模式之抽象工廠模式

抽象工廠模式介紹

在前面已經講解過工廠方法模式,這倆者有什麼區別呢?前面所說的工廠方法模式只會生產一種具體的產品,而抽象工廠模式生產出來的產品是不確定的。例如不同作業系統中控制元件的實現不一樣,展示效果也不一樣,對於作業系統如Android,iOS,WindowPhone本身構成一個產品類,而其控制元件如Button,TextView也構成產品類,兩種產品類兩種變化,各有各的特性。

抽象工廠模式的定義

為建立一組相關或者相互依賴的物件提供一個介面,而不需要指定它們的具體類。

抽象工廠模式的使用場景

一個物件族有相同約束時可以使用抽象工廠方法。舉個例子:Android,iOS,Phone下都有Button,TextView,兩者屬於控制元件的範圍,但是它們所在作業系統不一樣,所以程式碼邏輯實現也是不一樣的,這時就可以考慮使用抽象工廠方法模式來生產Android,iOS,phone下控制元件。

抽象工廠方法的類圖

角色介紹:

雖然抽象工廠方法種類繁多,但是主要分成四類:

  • AbstractFactory - 抽象工廠角色,它宣告一組用於建立一種產品的方法,每個產品對應一種方法,如上圖的AbstractFactory類中就定義了倆個方法,分別建立產品A和產品B
  • ConcreteFactory - 具體工廠角色,實現抽象工廠中定義的建立產品的方法,生成一組具體的產品,這些產品構成一個產品種類,每一個產品都位於某個產品等級結構中,如上述類圖中的ConcreteFactory1和ConcreteFactory2
  • AbstractProduct - 抽象產品角色,它為每種產品宣告介面,比如上圖中的AbstractProductA和AbstractProductB
  • ConcreteProduct - 具體產品角色,它定義具體工廠生產的具體產品物件,實現抽象產品介面中宣告的業務方法,如上圖中的ConcreteProductA1等

抽象工廠模式的簡單實現

工廠方法模式中,我們生產了三種車型,雖然整體流程一樣,但是各個車型的零件差別很大,而且廠家也不一樣,三種車型對應是一系列車,而零件比如輪胎、發動機、制動系統等對應的是一系列零件部件,兩者是倆種不同的產品型別,這時候就可以將抽象工廠模式運用到其中。

首先汽車需要生產輪胎,發動機,制動系統這三種部件

輪胎相關類

抽象產品角色

public abstract class Tire {
    public abstract void tire();
}

具體產品角色 

public class NormalTire extends Tire {
    @Override
    public void tire() {
        System.out.println("普通輪胎");
    }
}
public class SUVTire extends Tire {
    @Override
    public void tire() {
        System.out.println("越野輪胎");
    }
}

發動機相關類

抽象產品角色

public abstract class Engine {
    public abstract void engine();
}

具體產品角色  

public class DomesticEngine extends Engine {
    @Override
    public void engine() {
        System.out.println("國產發動機");
    }
}
public class ImportEngine extends Engine {
    @Override
    public void engine() {
        System.out.println("進口發動機");
    }
}

制動系統相關類

抽象產品角色 

public abstract class Brake {
    public abstract void brake();
}

具體產品角色   

public class NormalBrake extends Brake {
    @Override
    public void brake() {
        System.out.println("普通制動");
    }
}
public class SeniorBrake extends Brake {
    @Override
    public void brake() {
        System.out.println("高階制動");
    }
}

有了零件就要有工廠生產 

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

public abstract class CarFactory {
    public abstract Tire createTire();//生產輪胎
    public abstract Engine createEngine();//生產發動機
    public abstract Brake createBrake();//生產製動
}

每種車型的零件部件不同

奧迪工廠, 具體工廠角色

public class AudiCarFactory extends CarFactory {

    @Override
    public Tire createTire() {
        return new NormalTire();
    }

    @Override
    public Engine createEngine() {
        return new DomesticEngine();
    }

    @Override
    public Brake createBrake() {
        return new NormalBrake();
    }
}

賓士工廠, 具體工廠角色

public class BenzCarFactory extends CarFactory {

    @Override
    public Tire createTire() {
        return new SUVTire();
    }

    @Override
    public Engine createEngine() {
        return new ImportEngine();
    }

    @Override
    public Brake createBrake() {
        return new SeniorBrake();
    }
}

寶馬工廠, 具體工廠角色

public class BWMCarFactory extends CarFactory {

    @Override
    public Tire createTire() {
        return new NormalTire();
    }

    @Override
    public Engine createEngine() {
        return new ImportEngine();
    }

    @Override
    public Brake createBrake() {
        return new SeniorBrake();
    }
}

最後在一個Client中模擬

public class Client {

    public static void main(String[] args){
         //建立一個生產奧迪的工廠
         CarFactory carFactoryAudi = new AudiCarFactory();
         carFactoryAudi.createTire().tire();
         carFactoryAudi.createEngine().engine();
         carFactoryAudi.createBrake().brake();
         System.out.println();
        //建立一個生產賓士的工廠
         CarFactory carFactoryBenz = new BenzCarFactory();
        carFactoryBenz.createTire().tire();
        carFactoryBenz.createEngine().engine();
        carFactoryBenz.createBrake().brake();
        System.out.println();
        //建立一個生產寶馬的工廠
        CarFactory carFactoryBWM = new BWMCarFactory();
        carFactoryBWM.createTire().tire();
        carFactoryBWM.createEngine().engine();
        carFactoryBWM.createBrake().brake();
    }
}

輸出結果

普通輪胎
國產發動機
普通制動

越野輪胎
進口發動機
高階制動

普通輪胎
進口發動機
高階制動

上面只是模擬生產三種車系的情況,如果要生產其他車系,就要增加其他車系的工廠,不同車系構成一個產品類。如果對於奧迪工廠,我們把普通輪胎換成越野輪胎,雖然生產出來的車還是奧迪車型,但零件又和原本第一次生產出來的不一樣,不同零件又構成一個產品類。兩種產品類兩種變化。

總結

我們在開發中很少會出現多個產品種類的情況,大部分情況我們使用工廠方式模式就可以解決

優點:

分離介面與實現,客戶端使用抽象工廠來建立需要的物件,而客戶端根本不知道具體的實現類是誰,使其從具體的產品實現中解耦。

缺點:

(1)類檔案變多

(2)每當增加一個產品類就要修改抽象工廠,那麼所有具體的工廠類均會被修改,不容易擴充套件新的產品類