本文主要介紹一下如何使用c++設計成員變量可動態調整的抽象動態類結構。首先介紹一下項目中以前使用的一種類結構:靜態類結構
1.靜態類結構
很多時候,在項目開發中設計類結構時,我們往往有一種簡單、直接的慣性思維:原始數據是什么樣子,設計中類成員就包含相應的成員變量,這樣的類我把它稱之為靜態類結構。靜態類結構有兩個特點。
1.1特點一:類結構抽象能力不足。
靜態類結構強依賴於原始數據,是針對具體編程而不是針對抽象編程。一旦原始資源新增或者刪除字段,類結構就要相應的調整類成員變量,費事費力,而且是重復機械的無技術含量的勞動。例如:影視資源video.json,其內容如下:
清單1: video.json
{"id":"1009","name":"黃飛鴻之英雄有夢",,"isenabled":1,人","hotlevel":0,"source":0,"director":"周顯揚"}
針對該資源設計的靜態類VideoRecord結構:
清單2: class VideoRecord
1 class VideoRecord 2 { 3 public: 4 INT hot; 5 INT hotlevel; 6 INT source; 7 INT isenable; 8 string id; 9 string name; 10 string director; 11 ...... 12 }
假如現在video.json中新增字段copyright,videoRecord類就要增加相應的成員變量m_copyright。示例如下:
1.2 特點二:類結構泛化能力不足
一旦新增數據資源(例如:chanel.json),要么重新為該資源channel.json添加一個新的類結構ChannelRecord,要么合並channel.json和video.json中的所有字段,在原有VideoRecord類上新增成員。不管怎樣做,面對時常變化的需求,你可能會產生這樣直觀的感受:這樣的代碼抽象和泛化能力太弱了。
那么,能不能設計一種類結構,能夠很好的解決靜態類結構存在的所有問題,無論以后新增或者刪除一個字段,或者新增或刪除一種資源,都不必在讓我們為此花費時間和心思呢?為此,需要在設計類上面花點心思,下面輪到動態類結構粉墨登場了。
2.動態類結構
只需要做幾個改變,我們就能實現成員類型、個數等可動態伸縮調整的動態類結構啦。第一:重新設計類結構,定義指向所有的成員變量的指針的指針m_ppMember,可以通過m_ppMember訪問到所有指向成員變量的指針。
第二:有了m_ppMember指向所有的成員變量的指針,那么變量的個數和類型如何得知呢?這里就需要一個配置文件,指明資源中有多少字段,每個字段是什么類型。此外還需要記錄描述表,每種資源都會產生一個獨立的記錄描述表,記錄描述表通過讀取配置文件生成,供動態類結構使用,因此記錄描述表是動態類結構和配置文件的橋梁。由於Record並不含有成員變量類型等描述信息,Record對象的序列化和反序列化,必須借助m_type找尋到相應的記錄控制表,才能完成。
清單3:配置文件 config.json
"video": [ {"field":"name","type":"string"}, {"field":"id","type":"string"},
{"field":"actor","type":"string"}, //演員 {"field":"hot","type":"int"}, {"field":"hotLevel","type":"int"} ....... //其他字段,省略 ]
"channel": [ {"field":"name","type":"string"}, {"field":"id","type":"string"}, {"field":"comment","type":"string"}, //評論 {"field":"hot","type":"int"}, ....... //其他字段,省略 ]
清單4:記錄控制表 class recCtrlTable
1 #typedef string FIELD 2 #typedef int TYPE
2 #typedef int POS 3 class RecCtrlTable 4 { 5 private: 6 std::map<FIELD,std::pair<TYPE,POS>>m_recDes; //記錄控制表會根據config.json的配置,把每個field及其類型、位置,記錄在m_recDes中,供動態類Record使用 7 ...... 8 };
3.生成動態類對象
上面講述了如何設計動態類結構。有了動態類結構后,我們應該怎么使用該類生成一個類對象呢?舉個例子:還是使用上面的video.json,以其中的director,name和hot字段段:
(1)程序運行時首先加載config.json,生成RecCtrlTable類對象m_recCtrlTable對象;
(2)根據m_recCtrlTable中的m_recDes中的field,讀入video資源相應feild字段,並申請內存pChar1...pCharN,存放該field的值;
(3)最后把這些指針pChar1...pCharN的首地址賦值給動態Record對象中的m_ppMember;
從以上描述可以看出,每個Record類對象只記錄該對象的資源類型m_type和成員變量值的指針,Record對象的成員變量值的寫入和讀取,需要依賴於記錄控制表,這樣做,雖然增加了實現的復雜度,但是節約很大一部分內存。