c++工廠模式與new的區別

本文主要講解工廠模式比new方法的優勢。

爲什麼要用工廠模式來替代new?工廠模式相對於new方法有三個核心的好處:

1 可以讓產品類統一化入參。

#include <iostream>
#include <string>
using namespace std;

class AbstractProduct {
public:
    explicit AbstractProduct() : data(nullptr) {}
    virtual ~AbstractProduct() {}
    virtual void print() = 0;

protected:
    void *data;
};

class ProductInt : public AbstractProduct {
public:
    explicit ProductInt(int num) {
        data = new int(num);
    }
    ~ProductInt() override { delete(static_cast<int*>(data)); }

    void print() override {
        cout << "This is int type, data = " << *static_cast<int*>(data) << endl;
    }
};

class ProductBool : public AbstractProduct {
public:
    explicit ProductBool(bool b) {
        data = new bool(b);
    }
    ~ProductBool() override { delete(static_cast<bool*>(data)); }

    void print() override {
        cout << "This is bool type, data = " << *static_cast<bool*>(data) << endl;
    }
};

class ProductString : public AbstractProduct {
public:
    explicit ProductString(const string& str) {
        data = new string(str);
    }
    ~ProductString() override { delete(static_cast<string*>(data)); }

    void print() override {
        cout << "This is string type, data = " << *static_cast<string*>(data) << endl;
    }
};

template <typename T>
class Singleton {
public:
    static T& getInstance() {
        static Token token;
        static T instance(token);
        return instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

protected:
    struct Token{};

    Singleton() = default;
    virtual ~Singleton() = default;
};

//工廠也是一個單例
class Factory : public Singleton<Factory> {
public:
    Factory(Token token) {}
    ~Factory() = default;

    Factory(const Factory&) = delete;
    Factory& operator=(const Factory&) = delete;

    AbstractProduct* getProduct(int num) {
        return new ProductInt(num);
    }

    AbstractProduct* getProduct(bool b) {
        return new ProductBool(b);
    }

    AbstractProduct* getProduct(string str) {
        return new ProductString(str);
    }
};


int main()
{
    //不用工廠模式
    AbstractProduct *p1 = new ProductInt(1);
    p1->print();
    AbstractProduct *p2 = new ProductBool(false);
    p2->print();
    AbstractProduct *p3 = new ProductString("123");
    p3->print();
    //利用工廠模式,這樣用起來就非常爽了。
    Factory &f = Factory::getInstance();
    AbstractProduct *p4 = f.getProduct(1);
    p4->print();
    AbstractProduct *p5 = f.getProduct(false);
    p5->print();
    AbstractProduct *p6 = f.getProduct("123");
    p6->print();
    //釋放
    delete(p1);
    delete(p2);
    delete(p3);
    delete(p4);
    delete(p5);
    delete(p6);
    return 0;
}

2 一些操作(如:讀寫操作、數據庫操作、網絡請求等)延時很高,但又需要在構造函數中調用,且調用一次後緩存其內容,第二次直接讀取緩存會很快。當然可以將這些函數和緩存的內容提取成全局變量,但是他們還有更好的去出,那就是存放在其工廠當中。

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
using namespace std;

//普通版本
class Product01 {
public:
    Product01() {
        this_thread::sleep_for(chrono::seconds(1)); // 此時做一些延時很高的操作
        i = 1;
        cout << __func__ << ": "
             << chrono::system_clock::to_time_t(std::chrono::system_clock::now())
             << endl;
    }

private:
    int i;
};

//全局版本
int doSomething() {
    this_thread::sleep_for(chrono::seconds(1)); // 此時做一些延時很高的操作
    return 1;
}

class Product02 {
public:
    Product02(int i) : i(i) {
        cout << __func__ << ": "
             << chrono::system_clock::to_time_t(std::chrono::system_clock::now())
             << endl;
    }

private:
    int i;
};

//工廠模式版本
template <typename T>
class Singleton {
public:
    static T& getInstance() {
        static Token token;
        static T instance(token);
        return instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

protected:
    struct Token{};

    Singleton() = default;
    virtual ~Singleton() = default;
};

//工廠也是一個單例
class Factory : public Singleton<Factory> {
public:
    Factory(Token token) {
        i = doSomething();
    }
    ~Factory() = default;

    Factory(const Factory&) = delete;
    Factory& operator=(const Factory&) = delete;

    //本案例省略抽象產品和其他產品
    Product02* getProduct() {
        return new Product02(i);
    }

private:
    int i;

    int doSomething() {
        this_thread::sleep_for(chrono::seconds(1)); // 此時做一些延時很高的操作
        return 1;
    }
};


int main()
{
    //普通版本
    for (int i = 0; i < 3; ++i) {
        Product01 *p1 = new Product01();
        delete(p1);
    }

    //全局版本
    int g_i = doSomething();
    for (int i = 0; i < 3; ++i) {
        Product02 *p2 = new Product02(g_i);
        delete(p2);
    }

    //工廠版本
    Factory &f = Factory::getInstance();
    for (int i = 0; i < 3; ++i) {
        Product02 *p2 = f.getProduct();
        delete(p2);
    }

    return 0;
}

3 工廠方法可以對產品資源進行統一管理。比如:產品的循環利用。

#include <iostream>
#include <vector>
using namespace std;

class Product {
public:
    explicit Product(int num) : data(num) {
        cout << "construct data = " << data << endl;
    }
    ~Product() {
        cout << "destroy" << endl;
    }
    //前綴--重載
    Product& operator--() {
        //小於等於0表示產品已經沒用了。
        if (data > 0)
            --data;
        return *this;
    }
    void print() {
        cout << "data = " << data << endl;
    }
    int get() {
        return data;
    }
    void set(int num) {
        data = num;
    }
private:
    int data;
};

template <typename T>
class Singleton {
public:
    static T& getInstance() {
        static Token token;
        static T instance(token);
        return instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

protected:
    struct Token{};

    Singleton() = default;
    virtual ~Singleton() = default;
};

//工廠也是一個單例
class Factory : public Singleton<Factory> {
public:
    Factory(Token token) {}
    //負責資源管理,需要釋放v中的產品
    ~Factory() override {
        for (auto p : v) {
            delete(p);
        }
    }

    Factory(const Factory&) = delete;
    Factory& operator=(const Factory&) = delete;

    Product* getProduct(int num) {
        //重用已經廢棄的產品
        for (auto &p : v) {
            p->print();
            if (p->get() <= 0) {
                cout << "recycle product" << endl;
                p->set(num);
                return p;
            }
        }

        //沒有廢棄產品。
        Product *ret = new Product(num);
        v.emplace_back(ret);
        return ret;
    }

private:
    vector<Product*> v;
};


int main()
{
    Factory &f = Factory::getInstance();
    Product *p1 = f.getProduct(1);
    --(*p1);
    Product *p2 = f.getProduct(2);
    --(*p2);
    Product *p3 = f.getProduct(2);
    return 0;
}

輸出:

construct data = 1
data = 0
recycle product
data = 1
construct data = 2
destroy
destroy
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章