iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
0
自我挑戰組

初探設計模式系列 第 26

[ Day 26 ] 做好自己會做的就好啦 ~抽象工廠模式 ( Abstract Factory )

前言

到昨天為止,在 GoF [Design Pattern] 中所介紹的23種模式還剩下最後一種模式還沒介紹(本來以為都已經介紹完了)。工廠模式根據工廠端的實現方式(要哪個工廠或是製作哪個產品),有分成簡單工廠工廠方法模式抽象工廠模式

我們希望在擴充功能和修改功能時,總是只要動到其中一個地方的程式碼就可以,這樣的程式碼相對比較容易維護,而(某些)工廠模式違反了這個概念,除非使用反射的技巧或是其他方式,不然很多時候會需要同時修改到產品端和工廠端,兩方的程式碼···

定義

抽象工廠模式( Abstract Factory),提供一個建立一系列相關或互相依賴物件的介面,而無需指定它們具體的類別。

-- Design Pattern by GoF [大話設計模式 p.220]

使用情境與狀況

  • 產品涉及到多個產品系列時。
  • 未來可能需要抽換改變產品類別(系列)時。

UML

 Abstract Factory

  • AbstractProductA:產品A系列的介面。
  • ProductA1、ProductA2:A系列下的各個產品。
  • AbsctractProductB:產品B系列的介面。
  • ProductB1、ProductB2:B系列下的各個產品。
  • AbstractFactory:抽象工廠。
  • ConcreteFactory1、ConcreteFactory2:具體的工廠實現。

具體工廠的實現不一定要生產某一產品系列的產品(不需要同時是產品系列工廠),可以是這些系列中有某些共同點的商品的工廠。

Audi和BMW都有生產休旅車,而我的工廠專精生產休旅車,不一定需要會做某品牌全系列的商品。

在我想要生產其他車種時只需要抽換具體工廠即可(更換生產的產品)。

實作

BMW和Audi都有Jeep和SUV,用抽象工廠實現···

Audi的介面

public abstract class Audi {

    private String brand;
    private String type;

    public Audi(){
        this.brand = "Audi";
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getBrand() {
        return brand;
    }

    public String getType() {
        return type;
    }
}

BMW的介面

public abstract class BMW {

    private String brand;
    private String type;

    public BMW(){
        this.brand = "BMW";
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getBrand() {
        return brand;
    }

    public String getType() {
        return type;
    }
}

Audi的產品

public class AudiSUV extends Audi {

    public AudiSUV() {
        super();
        setType("SUV");
    }
}

public class AudiJeep extends Audi{
    public AudiJeep() {
        super();
        setType("Jeep");
    }
}

BMW的產品

public class BMWSUV extends BMW {
    public BMWSUV() {
        super();
        setType("SUV");
    }
}

public class BMWJeep extends BMW{
    public BMWJeep() {
        super();
        setType("Jeep");
    }
}

抽象工廠可以製作某品牌的Jeep或是SUV

public abstract class AbstractFactory {

    public abstract Audi createAudi();

    public abstract BMW createBMW();

}

Jeep工廠

public class JeepFactory extends AbstractFactory {
    @Override
    public Audi createAudi() {
        return new AudiJeep();
    }

    @Override
    public BMW createBMW() {
        return new BMWJeep();
    }
}

SUV工廠

public class SUVFactory extends AbstractFactory {
    @Override
    public Audi createAudi() {
        return new AudiSUV();
    }

    @Override
    public BMW createBMW() {
        return new BMWSUV();
    }
}

測試一下

public class Test {
    @org.junit.jupiter.api.Test
    public void test(){

        AbstractFactory factorySUV = new SUVFactory();
        System.out.println("----- SUV Factory -----");

        Audi suvAudi = factorySUV.createAudi();
        System.out.println(suvAudi.getBrand() + "的" + suvAudi.getType());

        BMW suvBMW = factorySUV.createBMW();
        System.out.println(suvBMW.getBrand() + "的" + suvBMW.getType());



        AbstractFactory factoryJeep = new JeepFactory();
        System.out.println("----- Jeep Factory -----");

        Audi jeepAudi = factoryJeep.createAudi();
        System.out.println(jeepAudi.getBrand() + "的" + jeepAudi.getType());

        BMW jeepBMW = factoryJeep.createBMW();
        System.out.println(jeepBMW.getBrand() + "的" + jeepBMW.getType());


    }
}

測試結果

----- SUV Factory -----
Audi的SUV
BMW的SUV
----- Jeep Factory -----
Audi的Jeep
BMW的Jeep

上一篇
[ Day 25 ] 每個人關心的點都不同 - 訪問者模式 (Visitor Pattern)
下一篇
[ Day 27 ] 初探設計模式 - 建立型模式
系列文
初探設計模式30

尚未有邦友留言

立即登入留言