さまざまな種類のデータベース (sqlite、postgres など) を操作できるデータベース ラッパーを書きたいので、実際に使用しているデータベースに関係なく、ユーザーが書いているコードは変わりません。
私の頭では、これは次のような抽象基本クラスを呼び出します。
class database {
public:
virtual bool query(const std::string &q) = 0;
// Other stuff
};
class sqlite : public database {
public:
bool query(const std::string &q) {
// Implementation
}
};
これは良さそうに見えますが、クエリ内で引数をエスケープするために可変個引数テンプレートを使用しています (そして、私はこのアイデアが本当に気に入っているので、それに固執したいと思います!)、残念ながら私の基本クラスはむしろ次のようになります:
class database {
public:
template <typename... Args>
bool query(const std::string &q, const Args &... args) {
// Implementation
}
};
ただし、テンプレート化された関数は仮想化できないため、これは抽象クラスの作成の妨げになります。これまでに思いついたのは、この構造だけです
template <class DatabaseType>
class database {
public:
template <typename... Args>
bool query(const std::string &q, const Args &... args) {
return database_.query(q, args...);
}
private:
DatabaseType database_;
};
これは機能しているように見えますが、同じ名前の関数を呼び出すだけのすべてのラッパーではdatabase_
、あまり良いスタイルとは思えません。これはここで選択したデザイン パターンですか、それともよりクリーンな、またはより慣用的な方法がありますか?