前言
优点:便于交换产品系列,改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用,不同的产品配置
让具体的创建实力过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中
缺点:如果产品需求来自增加功能,抽象工厂的改动地方比较大
最基本的访问数据库
这样写起来和数据库的耦合非常大,如果要更换数据库比较麻烦
static void Main(string[] args)
{
User user = new User();
//与SQL server耦合
SqlserverUser su = new SqlserverUser();
//插入用户
su.Insert(user);
//得到ID为1的用户
su.GetUser(1);
Console.Read();
}
工厂方法
IUser接口,用于客户端访问,接触与具体数据库访问的耦合
IFactory接口,定义一个创建访问User表对象的抽象的工厂接口
SqlserverUser类,用于访问SQL server的User
AccessUser类,用于访问Access的User
SqlServerFactory类,实现IFactory接口,实例化SqlserverUser
AccessFactory类,实现IFactory接口,实例化AccessUser
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
//IFactory接口,定义一个创建访问User表对象的抽象的工厂接口
interface IFactory
{
IUser CreateUser();
}
客户端代码
static void Main(string[] args)
{
User user = new User();
IFactory factory = new SqlserverFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
Console.Read();
}
工厂方法将业务逻辑和数据访问成功解耦,这样可以做到只要把 new SqlServer()改成new AccessFactory()就可以实现数据库访问的切换了,因为IUser接口的对象 iu 并不知道是在访问哪个数据库
但是如果是在功能上增加需求,那需要改动的地方比较多,就需要多写许多类
抽象工厂模式
添加了Department的客户端代码
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
//需确定实例化哪个数据库实例
//IFactory factory = new SqlserverFactory();
IFactory factory = new AccessFactory();
//与具体的数据库访问解除了依赖
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
iDepartment id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
Console.Read();
}
如果要更换数据库就只需要改IFactory factory =new AccessFactory()为IFactory factory = new SqlserverFactory()就可以实现数据库的切换了
工厂方法和抽象工厂模式的区别
只有一个User类和User操作类的时候是只需要工厂方法模式的,但现在显然数据库中有多个表,SQL Server和Access是两个不同的分类,所以解决涉及到多个产品系列的问题叫做抽象工厂模式、
优点:易于交换产品系列,让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中
缺点:修改功能时需要更改的类很多,不适用于修改功能
用简单工厂改进抽象工厂
当去掉IFactory、SqlserverFactory和AccessFactory三个工厂类,用DataAccess来取代
class DataAccess
{
private static readonly string db = "Sqlserver";
//private static readonly string db="Access";
public static IUser CreateUser()
{
IUser result = null;
switch(db)
{
case "Sqlserver":
result = new SqlserverUser();
break;
case "Access":
result = new AccessUser();
break;
}
return result;
}
客户端
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
IUser iu = DataAccess.CreateUser();
iu.Insert(user);
iu.GetUser(1);
iDepartment id = DataAccess.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
Console.Read();
}
Department的代码类似就没有贴出来,因为db是事先设置的值,所以这样客户端就可以生成数据库访问类实例,成功解耦,但是如果需要增加其他的数据库访问,就需要增加switch中的case了