用一段数据访问,只有ID和name的简单字段来做个探讨。
class User
{
public:
User();
User(int id, string name) :name(name), id(id){}
private://需要获得用户的ID和名字
int id;
string name;
};
用于操作User类的。
class SqlserverUser
{
public:
void Insert(User user);
User GetUser(int id);
};
具体实现如下:
User::User()
{
}
void SqlserverUser::Insert(User user)
{
//可以对user进行访问操作
cout << "在SQL Server中给User表增加一条记录" << endl;
}
User SqlserverUser::GetUser(int id)
{
cout << "在SQL Server中得到一条记录" << endl;
return User();
}
客户端代码如下:
int main()
{
User us(12, "xxx");
SqlserverUser s;
s.GetUser(12);
s.Insert(us);
}
SqlserverUser s;这一段和class User耦合,使这个对象被框死在Sql上面了,还记得依赖倒转原则,依赖于抽象类是最为关键的,为什么不利用多态来封装其变化呢?
我对于抽象工厂模式的理解就是,一个抽象工厂new一个抽象的父类,抽象的父类利用多态,衍生出子类的重写。
如下:
User是储存用户数据的类,只有ID和name两个字段
class User
{
public:
User() {}
User(string name, int id)
{
this->name = name;
this->id = id;
}
string name;
int id;
};
我需要实现的是什么,从不同数据库都可以取出用户数据,而且可以取出不同的用户。
定义一个获取用户信息的抽象类,解除与具体数据库访问的耦合,让其依赖于抽象,不依赖于实体。
class IUser
{
public:
virtual void Insert(User user) = 0;
virtual User GetUser(int id) = 0;
};
从不同数据库取出的用户数据,重写了获取用户信息的具体实现方法。
class SqlserverUser : public IUser
{
public:
virtual void Insert(User user)
{
cout << "在SQL Server 中给User表增加一条记录" << "name= " << user.name << endl;
}
virtual User GetUser(int id)
{
cout << "在SQL Server 中根据ID得到一条记录" << endl;
return User();
}
};
一个是SQL库,一个是Access库。
class AccessUser : public IUser
{
//用于访问Access的表,不同数据库的多态表现形式
public:
virtual void Insert(User user)
{
cout << "在Access 中给User表增加一条记录 name =" << user.name << endl;
}
virtual User GetUser(int id)
{
cout << "在 Access 中根据ID得到一条记录" << endl;
return User();
}
};
下面,我需要定义一个抽象工厂了,利用子类继承抽象的父类,重写。
/访问抽象库IUser的抽象工厂接口类
class IFactory
{
public:
virtual IUser* CreateUser() = 0;
};
以下为两个工厂子类重写抽象工厂,降低了工厂和数据库的耦合度。两方面都依赖于抽象。
class SqlserverFactory : public IFactory
{
public:
IUser* CreateUser()
{
return new SqlserverUser;//生成实例化Sql
}
};
class AccessFactory : public IFactory
{
public:
IUser* CreateUser()
{
return new AccessUser;//生成生产SQL数据库的工厂
}
};
最后客户端代码:
int main()
{
User user("小菜", 12);
IFactory *factory = new SqlserverFactory();
IUser * iu= factory->CreateUser();
iu->Insert(user);
iu->GetUser(1);
getchar();
}
此时IUser抽象接口不知道是在访问哪个数据库,这就是所谓的业务逻辑和数据访问解耦。但是里面需要改动的仍然很多,如果加一个其他表,比如增加部门,就需要增加一些类,增加代码量了。