一.首先来看一下最基本的数据访问程序,下面以"新增用户"和"得到用户"为例.
1.实体用户类代码如下,假设只有ID和Nane两个字段:
public class User
{
public int Uid { get; set; }
public string Name { get; set; }
}
2.sqlserverUser类---用于操作User类,代码如下:
public class SqlserverUser {
public void Insert(User user) {
Console.WriteLine("在SQL Server中给User表添加一条记录"); }
public User GetUser(int id) {
Console.WriteLine("在SQL Server中根据ID得到User表 一条记录");
return null;
}
}
3.客户端代码:
static void Main(string []args){
User user=new User();
SqlserverUser su=new SqlserverUser();
su.Insert(user) ; //插入用户
su.GetUser(1); //得到ID=1的用户
Console.Read();
}
总结:这样的写法虽然简单,但是当要转换数据库的时候,SqlserverUser su=new SqlserverUser();使得su这个对象被框死在SQL Server上了,解决这种问题,我们可以用工厂模式实现数据访问程序,下面来看一下工厂模式。
二.工厂模式的数据访问程序
1.首先写一个IUser接口,解除与具体数据库访问的耦合。代码如下:
public interface IUser {
void Insert(User user);
User GetUser(int id);
}
2.SqlserverUser类,用于访问Sql server 的User,代码如下
public class SqlserverUser : IUser {
public void Insert(User user){
Console.WriteLine("在SQL Server中给User表添加一条记录");
}
public User GetUser(int id) {
Console.WriteLine("在SQL Server中根据ID得到User表 一条记录");
return null;
}
}
2.1.AccessUser类,用于访问Access 的User,代码如下
public class AccessUser : IUser {
public void Insert(User user) {
Console.WriteLine("在Access中给User表添加一条记录");
}
public User GetUser(int id) {
Console.WriteLine("在Access中根据ID得到User表 一条记录");
return null;
}
}
3.工厂接口,用户访问User对象
public interface IFactory
{
IUser CreateUser();
}
4.1.SqlserverFactory:实现IFactory接口,实例化SqlserverUser类
public class SqlserverFactory:IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
4.2. AccessFactory:实现IFactory接口,实例化AccessUser类
public class AccessFactory:IFactory {
public IUser CreateUser()
{
return new AccessUser();
}
客户端代码:
static void Main(string []args){
User user=new User();
IFactory f=new SqlserverFactory(); //若要更改Access数据库,更改本句为IFactory f=new AccessFactory();即可。
IUser iu=f. CreateUser();
i.Insert(user) ; //插入用户
i.GetUser(1); //得到ID=1的用户
Console.Read();
}
总结:运用工厂模式虽然解决了业务逻辑和数据访问的解耦,但是数据库如果存在多表的时候,要更改的代码还是很多,要解决这种问题,下面可以用到抽象工厂模式。
三.抽象工厂模式
1概念:抽象工厂模式向客户端提供一个接口,使得客户端在不必指定具体类型的情况下,创建多个产品族中的对象
2使用抽象工厂模式的条件:
1) 一个系统不应依赖于产品如何被创建,组合和表达的细节。
2) 有多个产品族,而系统只消费其中一个族中的产品
3) 同属于一个产品族的产品是在一起使用的。
4) 系统提供一个产品的库,所有产品都是以同样的接口实现
下面添加多一个Department类作为例。
1.IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合,代码如下:
public interface IDepartment {
void Insert(Department pt);
Department GetDepartment(int id);
}
2.1.SqlserverUser类,用于访问Sql server 的Dpartment
public class SqlserverDepartment:IDepartment {
public void Insert(Department pt) {
Console.WriteLine("在SQL Server中给Department表添加一条记录");
}
public Department GetDepartment(int id) {
Console.WriteLine("在SQL Server中根据ID得到Department表 一条记录"); return null;
}
}
2.2.AccessUser类,用于访问Access 的Dpartment
public class SqlserverDepartment:IDepartment {
public void Insert(Department pt) {
Console.WriteLine("在SQL Server中给Department表添加一条记录");
}
public Department GetDepartment(int id) {
Console.WriteLine("在SQL Server中根据ID得到Department表 一条记录"); return null;
}
}
3.IFactory接口,定义一个创建访问Dpartment表的抽象工厂接口
public interface IFactory
{
IUser CreateUser();
IDepartment CreateDepartment(); //新增的接口方法
}
4.1.实现IFactory接口,实例化SqlserverUser类和SqlserverDepartment类
public class SqlserverFactory:IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
//新增的工厂
public IDepartment CreateDepartment()
{
return new SqlserverDepartment();
}
}
4.2.实现IFactory接口,实例化AccessUser类和AccessDepartment类
public class AccessFactory :IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
//新增的工厂
public IDepartment CreateDepartment()
{
return new AccessDpartment();
}
}
客户端代码:
static void Main(string[] args)
{
User user = new User();
Department pt = new Department();
IFactory f=new AccessFactory(); //现在只需实例化哪个数据库访问对象给f
IUser iu=f.CraetUser(); //与数据库解除了依赖
iu.Insert(user);
iu.GetUser(1);
IDepartment id = f.CreateDepartment();
id.Insert(pt);
id.GetDepartment(1);
Console.Read();
}
总结:这时候只需要 IFactory f=new AccessFactory();为 IFactory f=new SqlServerFactory();就可以实现了数据库访问的切换了,这里有多表并且SqlServer和Access又是两大不同分类,所以解决了这种涉及到多个产品的系列问题,这种模式就叫做抽象工厂模式。