先說一下background
前段時間想實現一個Sqlite localstorage的功能,對應不同的Model 實體有不同的table, 每一次sql操作的函數簽名中會有model實體中的struct結構作為參數,struct完全不同,無法抽象,如何實現呢?
方式1:
每一次操作實現一個函數,如update table1(model struct1) / update table2(model struct2), 這樣實現也有好處,簡單明了,每個函數簽名代表了最最直接的操作,最后把所有的函數簽名集合到一個大文件中暴露出來即可,
所有數據庫的操作也只有該大文件一個入口; 缺點是每個函數中大量重復邏輯不好抽離,感覺有點Low。
方式2:
一旦覺得有重復邏輯,抽象就會自然而然萌生。簡單粗暴,重復邏輯抽離為單獨函數,這只是封裝的思想,不過確實也能解決一些問題,只是對該場景感覺用處不大。
再有就是抽離接口,抽象基類,找到共通點,這應該是大多數的想法,也是我寫程序經常思考的方式。但是又有問題,這些函數簽名都不同(model struct不同),override沒有意義,簡單的繼承根本解決不了問題。
方式3:
模板,這確實是一種抽象能力,往往要求更高(我是不太會用模板),大量的開源項目幾乎都是模板,似乎扯遠了。。。。
不同的model structk可以用模板來抽象,但是對應的處理邏輯又是不同的(突然想到了什么,咦,這不是虛函數干的事嗎),又回到了方式2的問題
方式2 & 方式3:
模板繼承,base中轉化為特定的子類,於是有了下面的代碼
template<typename TableType, typename RowType> class SqliteTable { } template<typename TableType, typename RowType> template<typename KeywordType> bool SqliteTable<TableType, RowType>::execDeleteRowByKeyword(CppSQLite3DB* sqliteDB, const std::string& columnName, const KeywordType& keyword) { // convert base to child spefic instance return static_cast<TableType*> (this)->execDeleteRowByKeyword<KeywordType>(sqliteDB, columnName, keyword); }
主要其實就是在父類中直接轉化為子類的對象,在編譯期就實現了多態,不同於虛函數的運行期