建立型設計模式之抽象工廠模式
抽象工廠模式介紹
在前面已經講解過工廠方法模式,這倆者有什麼區別呢?前面所說的工廠方法模式只會生產一種具體的產品,而抽象工廠模式生產出來的產品是不確定的。例如不同作業系統中控制元件的實現不一樣,展示效果也不一樣,對於作業系統如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)每當增加一個產品類就要修改抽象工廠,那麼所有具體的工廠類均會被修改,不容易擴充套件新的產品類