Factory Pattern 工廠模式 C++

工廠模式

工廠模式(Factory Pattern)是面向對象程序設計中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且通過使用一個共同的接口來指向新創建的對象。

介紹

意圖: 定義一個創建對象的接口,使其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。

主要解決: 主要解決接口選擇的問題。

何時使用: 當我們明確計劃在不同條件下創建不同實例時。

如何解決: 使其子類實現工廠接口,返回的也是一個抽象的產品。

關鍵代碼: 創建過程在其子類執行。

應用實例: 如果我們需要一輛汽車,可以直接從工廠裏提貨,而不用管這輛汽車是怎麼被製造以及具體實現的。

優點:

  1. 一個調用者想創建一個對象,只需要知道其名稱。

  2. 擴展性高,如果想增加一個產品,只需要擴展一個工廠類(工廠方法模式)。

  3. 屏蔽了產品的具體實現,調用者只需要關心產品的接口。

缺點: 每次增加一個產品時,都需要增加一個具體類和對象實現工廠 (工廠方法模式),使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。

實現

以下使用 C++ 定義一個 Shape 接口以及實現 Shape 接口的子類。

工廠模式的 UML 圖

class Shape {
public:
    virtual void draw() = 0;
};

class Rectangle : public Shape {
private:
    int height = 0, width = 0;
    
public:
    Rectangle() {}
    
    Rectangle(int h, int w) {
        height = h;
        width = w;
    }
    
    void draw() {
        std::cout << "Inside Rectangle::draw() method." << std::endl;
        for (int i = 0; i < height; i++, std::cout << std::endl)
            for (int j = 0; j < width; j++)
                std::cout << "*";
        std::cout << std::endl;
    }
};

class Square : public Shape {
private:
    int side = 0;
    
public:
    Square() {}
    
    Square(int s) {
        side = s;
    }
    
    void draw() {
        std::cout << "Inside Square::draw() method." << std::endl;
        for (int i = 0; i < side; i++, std::cout << std::endl)
            for (int j = 0; j < side; j++)
                std::cout << "*";
        std::cout << std::endl;
    }
};

class Line : public Shape {
private:
    int len = 0;
    
public:
    Line() {}
    
    Line(int l) {
        len = l;
    }
    
    void draw() {
        std::cout << "Inside Line::draw() method." << std::endl;
        for (int i = 0; i < len; i++)
            std::cout << "*";
        std::cout << std::endl;
    }
};

如果按照一般方法,我們在調用子類函數 draw() 前需要使用子類的構造函數來創建對象。

int main() {
    Rectangle* r = new Rectangle(4, 5);
    Square* s = new Square(3);
    Line* l = new Line(10);
    
    r->draw();
    s->draw();
    l->draw();
    
    return 0;
}

輸出結果如下:

Inside Rectangle::draw() method.
*****
*****
*****
*****

Inside Square::draw() method.
***
***
***

Inside Line::draw() method.
**********

按照 Factory Pattern,我們不需要在創建子類對象時直接使用其構造函數。

定義工廠類 ShapeFactory

class ShapeFactory {
public:
    static void printParaError() {
        std::cout << "Parameter error!" << std::endl;
    }
    
    static void printTypeError() {
        std::cout << "Type name error!" << std::endl;
    }
    
    static Shape* getShape(std::string type) {
        if (type == "Rectangle") {
            return new Rectangle();
        }
        if (type == "Square") {
            return new Square();
        }
        if (type == "Line") {
            return new Line();
        }
        printTypeError();
        return nullptr;
    }
    
    static Shape* getShape(std::string type, std::vector<int> args) {
        if (type == "Rectangle") {
            if (args.size() == 2 && args[0] > 0 && args[1] > 0)
                return new Rectangle(args[0], args[1]);
            printParaError();
            return nullptr;
        }
        if (type == "Square") {
            if (args.size() == 1 && args[0] > 0)
                return new Square(args[0]);
            printParaError();
            return nullptr;
        }
        if (type == "Line") {
            if (args.size() == 1 && args[0] > 0)
                return new Line(args[0]);
            printParaError();
            return nullptr;
        }
        printTypeError();
        return nullptr;
    }
};

創建工廠類 ShapeFactory 用以生成具體子類對象,再分別調用其函數 draw()

int main() {
    ShapeFactory* f = new ShapeFactory();
    Shape* r = f->getShape("Rectangle", { 4, 5 });
    Shape* s = f->getShape("Square", { 3 });
    Shape* l = f->getShape("Line", { 10 });
    
    r->draw();
    s->draw();
    l->draw();
    
    return 0;
}

以上爲 Simple Factory Pattern 簡單工廠模式,當增加新的子類時需要修改工廠類,不遵循開閉原則。

以下爲 Factory Method Pattern 工廠方法模式 :

class Factory {
public:
    virtual Shape* getShape() = 0;
    
    virtual Shape* getShape(std::vector<int> args) = 0;
    
    static void printParaError() {
        std::cout << "Parameter error!" << std::endl;
    }
};

class RectangleFactory : public Factory {
public:
    Shape* getShape() {
        return new Rectangle();
    }
    
    Shape* getShape(std::vector<int> args) {
        if (args.size() == 2 && args[0] > 0 && args[1] > 0)
            return new Rectangle(args[0], args[1]);
        Factory::printParaError();
        return nullptr;
    }
};

class SquareFactory : public Factory {
public:
    Shape* getShape() {
        return new Square();
    }
    
    Shape* getShape(std::vector<int> args) {
        if (args.size() == 1 && args[0] > 0)
            return new Square(args[0]);
        Factory::printParaError();
        return nullptr;
    }
};

class LineFactory : public Factory {
public:
    Shape* getShape() {
        return new Line();
    }
    
    Shape* getShape(std::vector<int> args) {
        if (args.size() == 1 && args[0] > 0)
            return new Line(args[0]);
        Factory::printParaError();
        return nullptr;
    }
};
int main() {
    RectangleFactory* rf = new RectangleFactory();
    SquareFactory* sf = new SquareFactory();
    LineFactory* lf = new LineFactory();
    Shape* r = rf->getShape({ 4, 5 });
    Shape* s = sf->getShape({ 3 });
    Shape* l = lf->getShape({ 10 });
    
    r->draw();
    s->draw();
    l->draw();
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章