本文主要講解工廠模式比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