首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

命令模式實現物件持久化:橋接面向對象與關係數據庫

     編輯:關於VC++

開發背景

面向對象分析設計中,實體物件需持久化存儲。檔案存儲難以表達物件關聯、效能不足;物件導向資料庫(OODB)尚不成熟。關係型資料庫(RDBMS)技術成熟、普及率高,但與 OO 語言存在「阻抗失配」。為降低耦合、提升開發效率,需在應用系統與資料庫間建立物件存儲模組。

實現策略

資料庫結構特點

資料表對應實體物件,欄位對應屬性。各表結構不同(欄位數、型別、約束),難以統一類別表示;但共同擁有表名、CRUD 操作。

實體物件與資料表映射

建立抽象基類 CEntity:

  • 成員:實體名稱(對應表名)、資料庫連接物件指標。
  • 介面:虛擬函數 Read()、Write()、Delete() 等,參數為資料庫連接。
  • 派生類實作具體屬性與存取邏輯:以實體名開啟記錄集,欄位值與屬性雙向映射。

命令模式組織存儲操作

參考 GoF 命令模式:

  • Command(抽象命令):定義 Execute()、Undo() 介面。
  • ConcreteCommand(具體命令):封裝接收者(CEntity 派生類)的服務,如 SaveCommand、LoadCommand、DeleteCommand。
  • Invoker(調用者):CStorage 管理資料庫連接,執行命令佇列,提供 SaveEntity()、ReadEntity() 等統一服務。
  • Receiver(接收者):實體物件本身。

優勢:命令與演算法分離、調用者與具體命令解耦、命令可序列化/記錄/撤銷、新增命令無需修改既有代碼。

核心類別設計

CEntity(抽象基類)

class CEntity {
public:
    CEntity(const CString& name);
    virtual ~CEntity();
    virtual BOOL Read(CAdoRecordSet* rs) = 0;
    virtual BOOL Write(CAdoRecordSet* rs) = 0;
    virtual BOOL Delete(CAdoRecordSet* rs) = 0;
protected:
    CString m_strEntityName; // 對應資料表名
};

CEntitySet<T>(模板集合類)

參數 T 必須繼承 CEntity。負責依 SQL 查詢生成實體集合:

template <class T>
class CEntitySet {
public:
    CEntitySet(const CString& name);
    BOOL Execute(); // 執行查詢,填充 m_vecEnt
    T* operator[](int idx) const;
    int GetSize() const;
    void SetSQLString(const CString& sql);
    void SetConn(CAdoConnection* conn);
private:
    CString m_strEntityName, m_strSQL;
    CAdoConnection* m_pConn;
    std::vector<T*> m_vecEnt;
};

Execute() 實作:開啟 Recordset → 逐筆 new T → 呼叫 Read() 映射欄位 → 加入向量。

CStorage(存儲管理器)

  • 管理 ADO 連接(初始化/關閉)。
  • 提供 SaveEntity(CEntity*)、ReadEntity(CEntity*)、DeleteEntity(CEntity*)。
  • 內部以 CEntity* 多態呼叫實體的私有存取介面,確保封裝性。

應用範例:圖書管理系統

// 初始化
m_Storage.SetConnString("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Book.mdb");
m_Storage.Initialize();

// 借書:關聯視圖查詢 → 實體存儲
CBorrowBook borrowbook; borrowbook.SetBookNumber("10001");
m_Storage.ReadEntity(&borrowbook);
CBorrow borrow;
borrow.SetPersonName(borrowbook.GetPersonName());
borrow.SetBorrowDate(borrowbook.GetBorrowDate());
m_Storage.SaveEntity(&borrow);

// 查詢價格 > 90 的圖書
CEntitySet<CBook> books("book");
books.SetConn(m_Storage.GetConn());
books.SetSQLString("price>90");
books.Execute();
for (int i=0; i<books.GetSize(); ++i) {
    CBook* p = books[i];
    // 顯示至 ListCtrl...
}

關鍵設計要點

  1. 實體名 = 資料表名,約定優於配置。
  2. 實體的資料庫操作介面聲明為 private,僅 CStorage/CEntitySet 透過基類指標多態調用,對應用層隱藏。
  3. 模組與資料存取技術解耦:核心邏輯不依賴 ADO,替換為 ODBC/DAO/JDBC 僅需調整連接層。
  4. 效能權衡:物件映射層引入額外開銷,但換取架構彈性與開發效率。

總結

本文展示以命令模式為核心、結合模板技術與多態機制的物件持久化框架。該設計實現了實體物件與關係表的透明映射,支援動態查詢集合生成,且擴充新實體無需修改框架核心,有效解決了 OO 應用與 RDBMS 的整合難題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved