抽象工厂模式

一,抽象工厂模式

1.1,最基本的数据访问程序

class User
{
	private int id;
	private string name;
};

class SqlServerUser
{
	public void insert(User &user)
	{
		// 在SQL Server中给User表增加一条记录
	}

	public void getUser(int id)
	{
		// 根据id从User表中获取一条记录
	}
}

// 客户端代码
static void main()
{
	User *pUser = new User();
	SqlServerUser *pSu = new SqlServerUser();

	pSu->insert(pUser);  // 插入一条记录到User表
	pSu->getUser(1);     // 获取id为1的user
}

程序分析:

之所以不能直接更换数据库,因为SqlServerUser *pSu = new SqlServerUser()把SQL Server数据库硬编码到程序里。

1.2,使用工厂模式的数据访问程序

定义IUser接口,解除与具体数据库访问的耦合

在这里插入图片描述

定义IFactory接口,定义一个创建访问User表对象的抽象的工厂接口

在这里插入图片描述

class SqlServerFactory : public IFactory
{
	public IUser *createUser()
	{
		return new SqlServerUser();
	}
}

class AccessFactory : public IFactory
{
	public IUser *createUser()
	{
		return new AccessUser();
	}
}

// 客户端代码
static void main()
{
	User *pUser = new User();
	
	IFactory *pFactory = new SqlServerFactory();
	IUser *pIU = pFactory->createUser();

	pIU->insert(pUser);  // 插入一条记录到User表
	pIU->getUser(1);     // 获取id为1的user
}

程序分析:

由于多态的原因,pIU事先并不知道是在访问哪个数据库,却可以在运行时很好地完成任务,这就是业务逻辑与数据访问的解耦。

1.3,抽象工厂模式的优点与缺点

优点:

  1. 易于交换产品序列,由于具体的工厂类,例如:IFactory factory = new AccessFactory(),在一个应用中只需要在初始化的时间出现一次,这就使得修改一个应用的具体工厂非常的容易,它只需要改变具体工厂即可使用不同的数据库配置,例如:如果想把数据库切换成SQL Server只需要修改IFactory factory = new SQLServerFactory(),只需要改变具体的工厂类,其它地方都不需要修改,非常的方便。
  2. 把具体的创建实例的过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码里。

缺点:

  1. 如果需求增加功能要修改的地方比较的多,例如:新增加一个Department表,至少要增加三个必要的类:IDepartment、SqlserverDepartment、AccessDepartment,同时IFactory、SqlserverFactory、AccessFactory都需要修改,新增加一个类要对已有的三个类进行修改,不符合"开放-封闭"原则,下面是需要增加的代码。
  2. 如果在程序的很多地方用到IUser,那么在这些用到地方的开始位置要声明IFactory factory = new SQLServerFactory(),当把数据库切换成Access时,就要对程序中所有声明IFactory factory = new SQLServerFactory()语句的地方进行修改。这样不能解决要更换数据库时,改动一处就完全更改的要求。
class IFactory
{
	public IUser *createUser();

	// 新增代码
	IDepartment *createDepartment()
};

class SqlServerFactory : public IFactory
{
	public IUser *createUser()
	{
		return new SqlServerUser();
	}

	// 新增代码
	public IDepartment *createDepartment()
	{
		return new SqlServerDepartment();
	}
};

class AccessFactory : public IFactory
{
	public IUser *createUser()
	{
		return new AccessUser();
	}

	// 新增代码
	public IDepartment *createDepartment()
	{
		return new AccessDepartment();
	}
};

1.4,使用简单工厂来改进抽象工厂

使用DataAccess类替换掉IFactory、SqlserverFactory、AccessFactory三个工厂方法

class DataAccess
{
    // 要访问的数据库名称,在这里可以更改成Access
	private static string db = "Sqlserver";

	public static IUser createUser()
	{
		IUser *result = null;
		switch(db)
		{
		case "Sqlserver":
			result = new SqlserverUser();
			break;
		case "Access":
			result = new AccessUser();
			break;
		}
		return result;
	}

	public static IDepartment createDepartment()
	{
		IDepartment *result = null;
		switch(db)
		{
		case "Sqlserver":
			result = new SqlserverDepartment();
			break;
		case "Access":
			result = new AccessDepartment();
			break;
		}
		return result;
	}
}

// 客户端代码
static void main()
{
	User *pUser = new User();
	IUser *pIU = DataAccess.createUser();

	pIU->insert(pUser);  // 插入一条记录到User表
	pIU->getUser(1);     // 获取id为1的user
}

程序分析:

使用DataAccess类替换掉IFactory、SqlserverFactory、AccessFactory三个工厂方法,客户端只需要DataAccess.createUser()或DataAccess.createDepartment()来生成具体的数据库访问实例,客户端没有出现任何一个SQL Server或Access这样的字样,达到了解耦的目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值