我的英语不足以解释我的问题。但我会尽我所能。
我曾经是一名Java程序员,但已经使用C ++一年多了。总是困扰我的一件事是从网络创建业务对象的策略(比如通过SNMP,Web服务或其他数据源......)并将其保存到数据库并在应用程序启动时加载它。通常我的设计如下:
class Object{
/* this is just a demonstration, in real code, there are all kinds of Object and has relationships*/
friend class DBConnection;
friend class SNMPConn
private:
std::string& m_strName;
//... all kinds of properties
}
class DBConnection
{
int load(Object& obj);
int save(Object& obj);
int modify(Object& obj);
int loadAll(std::vector);
}
class SNMPConn
{
int load(Object& obj);
...
}
我不赞同的是“朋友班......”的路线。它破坏了封装。我找到了一些框架,比如litesql(sourceforge.net/apps/trac/litesql)和其他商业框架,但这些框架很难与我现有的代码集成。我试图手动完成并试图找到这种工作的共同策略。
我是一名Java开发者,用C ++设计是我不擅长的。我不知道这种设计工作的最佳实践是什么。
答案 0 :(得分:1)
正如我从这个问题中理解的那样(在读写DB或SNMP连接时打破封装),首先你需要一个合适的设计来消除这些“朋友”。请为连接(即IDBConnection)定义一个抽象类,也是持久对象(即IPersistent)。您可以使用“抽象工厂”模式来创建它们。此外,隔离加载并将方法保存到另一个类,并使用“访问者模式”从/向数据库初始化或保存对象。
另一点,如果您的应用程序需要嵌入式数据库,请使用SQLite,它有很多优秀的C ++包装器。希望它有所帮助
答案 1 :(得分:0)
以下是我在伪代码中的表现方式:
class Result {
public:
int getField(name);
string getField(name);
}
class Connection {
public:
void save(list<pair<string, string>> properties);
Result query();
}
class DBConnection {
private:
class DBResult : public Result {
}
public:
Result query() {
return ( DBResult );
}
void save
}
class Object {
public:
void load(Result);
void save(Connection) {
// make properties list
connection.save(properties);
}
}
如果没有Java风格的反思,那可能就是我没有进入“朋友”关系的方式。然后,您没有将连接逻辑的知识紧密地耦合到连接类中。
...
您也可以构建模板函数来执行此操作,但您仍需要朋友关系。
class Object {
public:
friend template<class Conn, class Obj> load(Conn c, Obj o);
friend template<class Conn, class Obj> save(Conn c, Obj o);
}
load<Connection, Object>(Connection c, Object o) {
//access o.private to load into c
}
我不确定自己走哪条路。在一个方面,您将加载/保存逻辑封装在Object类中,这对于本地化非常有用,但它可能会将持久性和业务逻辑紧密地耦合在一个位置。