我正在设计一个数据库浏览应用程序,到目前为止已经支持MySQL,但最近我也开始实现支持Sqlite,并且在设计连接体系结构的方式时我面临一些丑陋。这只是关于“连接”部分(即:获取用户/ db / host,或sqlite文件名),而不是数据库功能。这已经整理好了。
我有一个基类“Connection”,它暴露像name()
这样的“普通”方法,或者像virtual string fullLocation() = 0
那样的纯虚方法,它返回一个可用于识别数据库的字符串(例如:database@host
用于MySql,或/etc/mydb.sqlite
用于Sqlite)。
现在,用户当然需要指定他想要连接的数据库,因此在应用程序的GUI中,他只需选择类型然后填写凭据。在这里我的麻烦开始了。我创建了一个MySqlConnection
和一个SqliteConnection
类,这两个类都派生自Connection
,但大多数情况下我最终得到的结果如下:
Connection* c = 0;
if(gui->engine_name() == "MYSQL")
{
string host = gui->getHost();
string user = gui->getUser();
string password = gui->getPassword();
int port = gui->getPort();
string db = gui->getDatabase();
c = new MySqlConnection(host, user, password, db, port);
}
else
{
string dbFile = gui->getSqliteDbFile();
c = new SqliteConnection(dbFile);
}
string meta = application->use_connection(&c);
我担心,由于这两个数据库引擎的性质如此不同,这将在整个应用程序中继续。
您是否有一些如何以优雅的方式解决这个问题的指导?
答案 0 :(得分:0)
更优雅的方法是设计工厂类并在该工厂的GenerateConnection()
方法中处理GUI输入:
void ConnectionFactory::GenerateConnection(Connection* c)
{
if(gui->engine_name() == "MYSQL")
{
string host = gui->getHost();
string user = gui->getUser();
string password = gui->getPassword();
int port = gui->getPort();
string db = gui->getDatabase();
c = new MySqlConnection(host, user, password, db, port);
}
else
{
string dbFile = gui->getSqliteDbFile();
c = new SqliteConnection(dbFile);
}
}
如果你不喜欢对gui的依赖,你可以定义一个名为Parameters的结构,并根据gui输入更新它的实例,并将该对象赋予连接工厂的连接生成方法。
答案 1 :(得分:0)
你需要模式工厂,它将以抽象的方式为你创建连接。这是肤浅的答案。 这个工厂可以很好地使用Builder模式进行参数化。这样的事情:
ParamBuilder *b = new ParamBuilder;
if(gui->engine_name() == "MYSQL")
{
b->setHost(gui->getHost())
->setUser(gui->getUser());
->setPassword(gui->getPassword());
...
}
else
{
b->setFile(gui->getSqliteDbFile());
}
Connection *c = globalConnectionFactory->createConnection(b);