iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Software Development

深入淺出設計模式 - 使用 C++系列 第 6

[Day 06] 讓工廠再解藕 - 抽象工廠模式 (Abstract Factory Pattern)

  • 分享至 

  • xImage
  •  

抽象工廠 (Abstract Factory)

抽象工廠模式提供一個介面來建立相關或相依的物件家族,而不需要指定具體類別
Head First Design Patterns, 2nd (p.156)

  • 定義
    • 抽象工廠模式 (Abstract Factory pattern) 與工廠模式 (Factory Pattern) 是在工廠模式上的另一層抽象 (another layer of abstraction over factory pattern)
    • 抽象工廠模式圍繞一個超類別的工廠 (super-factory) 運作,這個超類別的工廠負責 Create 其他工廠
  • 目的
    • 用一個工廠介面來產生一系列相關的物件,但實際建立哪些物件由實作工廠的子類別來實現
  • 抽象工廠組成
    • Abstract Factory: 聲明一個用於創建抽象產品對象的操作介面
    • Concrete Factory: 實作在 Abstract Factory 中聲明的操作以創建具體產品對象
    • Abstract Product: 聲明一個抽象產品的介面 (給 Product 子類別繼承並決定實作)
    • Product: 定義由相對應的具體工廠創建的產品對象,並實現 Abstract Product 介面
    • Client: 僅使用 AbstractFactory 和 AbstractProduct 類別聲明的介面

範例 (From Geeksforgeek)

https://ithelp.ithome.com.tw/upload/images/20230918/20138643EfS4oKZBSf.png

// 車型
enum class CarType {
    MICRO, MINI, LUXURY
};
// 產地
enum class Location {
    DEFAULT, USA, INDIA
};

// 抽象車輛類
class Car {
public:
    Car(CarType model, Location location) : model(model), location(location) {}

    virtual void construct() = 0;

    std::string getModel() {
        return (model == CarType::MICRO) ? "MICRO" : (model == CarType::MINI) ? "MINI" : "LUXURY";
    }

    std::string getLocation() {
        return (location == Location::DEFAULT) ? "DEFAULT" : (location == Location::USA) ? "USA" : "INDIA";
    }

    virtual ~Car() {}

protected:
    CarType model;
    Location location;
};

class LuxuryCar : public Car {
public:
    LuxuryCar(Location location) : Car(CarType::LUXURY, location) {
        construct();
    }

    void construct() override {
        std::cout << "Connecting to luxury car" << std::endl;
    }
};

class MicroCar : public Car {
public:
    MicroCar(Location location) : Car(CarType::MICRO, location) {
        construct();
    }

    void construct() override {
        std::cout << "Connecting to Micro Car" << std::endl;
    }
};

class MiniCar : public Car {
public:
    MiniCar(Location location) : Car(CarType::MINI, location) {
        construct();
    }

    void construct() override {
        std::cout << "Connecting to Mini car" << std::endl;
    }
};

class CarFactory {
public:
    static Car* buildCar(CarType type) {
        Car* car = nullptr;
        Location location = Location::INDIA;

        switch (location) {
        case Location::USA:
            car = USACarFactory::buildCar(type);
            break;

        case Location::INDIA:
            car = INDIACarFactory::buildCar(type);
            break;

        default:
            car = DefaultCarFactory::buildCar(type);
        }

        return car;
    }

private:
    class USACarFactory {
    public:
        static Car* buildCar(CarType model) {
            Car* car = nullptr;

            switch (model) {
            case CarType::MICRO:
                car = new MicroCar(Location::USA);
                break;

            case CarType::MINI:
                car = new MiniCar(Location::USA);
                break;

            case CarType::LUXURY:
                car = new LuxuryCar(Location::USA);
                break;
            }

            return car;
        }
    };

    class INDIACarFactory {
    public:
        static Car* buildCar(CarType model) {
            Car* car = nullptr;

            switch (model) {
            case CarType::MICRO:
                car = new MicroCar(Location::INDIA);
                break;

            case CarType::MINI:
                car = new MiniCar(Location::INDIA);
                break;

            case CarType::LUXURY:
                car = new LuxuryCar(Location::INDIA);
                break;
            }

            return car;
        }
    };

    class DefaultCarFactory {
    public:
        static Car* buildCar(CarType model) {
            Car* car = nullptr;

            switch (model) {
            case CarType::MICRO:
                car = new MicroCar(Location::DEFAULT);
                break;

            case CarType::MINI:
                car = new MiniCar(Location::DEFAULT);
                break;

            case CarType::LUXURY:
                car = new LuxuryCar(Location::DEFAULT);
                break;
            }

            return car;
        }
    };
};

int main() {
    Car* car1 = CarFactory::buildCar(CarType::MICRO);
    Car* car2 = CarFactory::buildCar(CarType::MINI);
    Car* car3 = CarFactory::buildCar(CarType::LUXURY);
}

Reference

[1]. https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/abstractFactory1.html
[2]. https://www.geeksforgeeks.org/abstract-factory-pattern/


上一篇
[Day 05] 烘焙物件的精華 - 工廠模式 (Factory Pattern)
下一篇
[Day 07] 經典比較 — Simple Factory / Factory / Abstract Factory
系列文
深入淺出設計模式 - 使用 C++37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言