一,依賴倒置原則
1.1,什麼是依賴倒置?
高層次的子產品不應該依賴于低層次的子產品,他們都應該依賴于抽象。抽象不應該依賴于具體實作,具體實作應該依賴于抽象。也就是說要面向接口程式設計,不能面向實作程式設計。
1.2,應用場景
做一個訂單處理系統,主要的操作是往資料庫裡添加記錄,下面實作的是面向實作程式設計的版本,例如:
// SQLServer
class SQLServer
{
public:
void insert()
{
// 往SQL資料庫添加一條記錄
}
};
// Access
class Access
{
public:
void insert()
{
// 往Access庫添加一條記錄
}
};
// 訂單類
class Order
{
public:
SQLServer *m_pSQLServer;
Access *m_pAccess;
String m_sDBName;
Order(String sDBName):m_sDBName(sDBName)
{
m_pSQLServer = new SQLServer();
m_pAccess = new Access();
}
void insert()
{
switch(m_sDBName)
{
case "SQLServer":
m_pSQLServer->insert();
break;
case "Access":
m_pAccess->insert();
break;
}
}
};
程式分析:
如果此時底層的資料庫變成Oracle資料庫,那就要重新修改原來的Order類,如果有更多的資料庫添加進來,就要在Order中增加更多的case語句,隻要底層的資料庫發生變動,Order類就要跟着變動。造成這個問題的主要原因就是,Order高層子產品直接依賴于底層的具體實作。根據依賴倒置原則,重構前面的系統,下面是重構後的系統圖與具體實作
// 資料庫通路接口
class DBManager
{
public:
void insert();
}
// SQLServer
class SQLServer : public DBManager
{
public:
void insert()
{
// 往SQL資料庫添加一條記錄
}
};
// Access
class Access : public DBManager
{
public:
void insert()
{
// 往Access庫添加一條記錄
}
};
// 訂單類
class Order
{
public:
DBManager *m_pDBManager;
Order(DBManager *manager) : m_pDBManager(manager){}
void insert()
{
m_pDBManager->insert();
}
};
程式分析: 重構後的系統,高層與底層子產品都是依賴于DBManager接口,DBManager接口相對來說是比較固定不容易發生變化的。此時,及時底層的資料庫更換成Oracle,隻用添加一個新的類實作DBManager接口,Order類不會發生變動。