第31章 新的設計模式(2)
31.2 物件池模式
31.2.1 定義和類圖
(1)定義:物件池是一種設計模式,它通過管理有限物件複用來共享某些稀少或必須付出昂貴代價的資源。
(2)類圖:
31.2.2 物件池的擴充套件介面
(1)兩級物件池方式:空閒物件池和已用物件池
(2)利用Wrapper模式包裝複用物件,使附加一些屬性(如空閒時間)
class wrapper
{
private:
int useTime; //開始使用時間
int unuseTime; //開始空閒時間
//其他附加屬性
Object* reusable; //複用物件的指標
};
(3)空閒物件池:存放目前還沒有分配出去的空閒複用物件
①wrapper* get(string model, string strategy);//獲得一個空閒物件(這裡的策略指分配空閒物件的策略,如最大空閒時間分配或隨機分配等)
②void add(string model, wrapper* object);//加入一個空閒物件
(4)己用物件池:存放正在被客戶端使用的連線。
①void close(wrapper* object); //將物件從己用物件池中刪除
②void put(wrapper* object); //加入一個複用物件
31.2.3 複用物件的建立和消亡
(1)複用物件建立: wrapper* create(string model);//注意是private屬性。model為複用物件的型別。由於程式並不知道建立何種複用物件,這裡通過Bridge將實際建立物件轉交objectBridge->create(model);
wrapper* create(string model)
{
wrapper* ret =NULL;
if (objectNumber < maxObjectNumber)
{
objectNumber++;
//建立新的被包裝的物件
ret = new wrapper(objectBridge->create(model)); //轉交
}
return ret;
}
(2)複用物件的消亡:void remove(wrapper*);//從物件池中刪除,即物理刪除。private
void remove(wrapper* o) { objectNumber--; objectBridge->remove(o.object); }
(3)獲取的複用物件:在需要一個Reusable物件時,客戶端呼叫AcquireReusable方法。如果池是空的,那麼AcquireReusable方法建立一個Reusable物件(如果能夠),否則,就等待知道有Reusable物件返回集合。
31.2.4 manager object的管理策略
(1)物件的產生策略
①void setInitPoolSize();//定義物件池初始化時預設的物件數量
②void createByStrategy();//採用何種策略建立空閒物件
(2)物件的回收策略
①客戶通過acquiredReusable獲得一個複用物件,然後在使用完後主動歸還得複用物件。
②但不能假設客戶端使用完物件後,肯定會歸還物件,而且有時還有可能客戶端程式因為程式異常或死鎖使得物件無法歸還。設定複用物件最大使用時間:void setMaxUseTime(long time);當超時的時候就強制回收。超過最大額定值時(回收由時間執行緒定時檢查)。
(3)物件的消亡策略
①當複用物件數量超過額定值時,系統歸還當前空閒複用物件所佔資源以減輕系統 的負擔。
②策略:如一次性將空閒物件全部回收或部分回收。
【程式設計實驗】模擬一個數據庫連線池進行實現
//新設計模式——物件池模式
//場景:資料庫連線池
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef void Object;
//使用者需要的實際的東西都要實現這個介面
class IConnection
{
public:
virtual Object* getConnection() = 0;
virtual void setConnection(Object* obj) = 0;
};
//實現類:使用者真正需要的東西,比如資料庫連線
class Connection : public IConnection
{
Object* conn;
public:
Object* getConnection(){return conn;}
void setConnection(Object* obj)
{
conn = obj;
}
};
//池子中放的東西(具有狀態及使用者實際需要的東西)
class PoolItem
{
private:
bool m_isUse;
IConnection* conn;
public:
PoolItem(IConnection* conn)
{
this->conn = conn;
m_isUse = false;
}
bool isUse(){return m_isUse;}
void setIsUse(bool value)
{
m_isUse = value;
}
IConnection* getConnection()
{
return conn;
}
};
//池子管理物件
class PoolManager
{
private:
vector<PoolItem*> items;
public:
//往池子裡放東西(多執行緒時可考慮同步)
void add(IConnection* conn)
{
items.push_back(new PoolItem(conn));
}
//釋放物件(多執行緒時可考慮同步)
void release(IConnection* conn)
{
vector<PoolItem*>::iterator iter = items.begin();
while( iter != items.end())
{
PoolItem& item = *(*iter);
if(item.getConnection() == conn)
{
item.setIsUse(false);
break;
}
++iter;
}
}
//得到池中的物件(多執行緒時可考慮同步)
IConnection* get()
{
IConnection* ret = NULL;
vector<PoolItem*>::iterator iter = items.begin();
while( iter != items.end())
{
PoolItem& item = *(*iter);
if(! item.isUse())
{
item.setIsUse(true);
ret = item.getConnection();
break;
}
++iter;
}
return ret;
}
};
//連線池物件(使用者真正需要關心的池子)
class ConnectionPool
{
private:
static PoolManager manager;
public:
//批量新增連線物件
void addConnections(int count)
{
for(int i=0; i<count; i++)
{
manager.add(new Connection());
}
}
//得到連線物件
static IConnection* getConnection()
{
return manager.get();
}
//釋放連線
static void release(IConnection* conn)
{
manager.release(conn);
}
//清除所有連線
static void clearConnection()
{
}
};
PoolManager ConnectionPool::manager;
int main()
{
return 0;
};
31.2.5 小結
(1)該模式通過定義6個介面和兩個抽象擴充套件物件(RealObjectCreator和PoolManager)。通過實現RealObjectCreator抽象物件,可以將整個物件池模式擴充套件到新的應用領域 。
(2)通過實現PoolMnanger抽象物件,可以針對不同的不物件實現不同的管理策略,來完成複用物件的建立、消亡和管理等諸多工作。