第15章 就不能不换DB呢?--抽象工厂模式
15.2 最基本的数据访问程序
class User
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value;}
}
private string _name;
public string Name
{
get { return _name; }
set {_name=_value; }
}
}
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;
}
}
客户端代码
static void Main(string[] args)
{
User user = new User();
SqlserverUser su = new SqlserverUser();
su.Insert(user);//插入用户
su.GetUser(1);//得到ID为1的用户
Console.Read();
}
工厂方法模式是定义一个用于创建对象的接口,让子类决定实例化哪一个类。
15.3 用了工厂方法模式的数据访问程序
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
SqlserverUser类,用于访问SQL Server的User
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;
}
}
AccessUser类,用于访问Access的User
{
public void Insert(User user)
{
Console.WriteLine(“在Access中给User表增加一条记录”);
}
public User GetUser(int id)
{
Console.WriteLine(“在Access中根据ID得到User表一条记录”);
return null;
}
}
IFactory接口
interface IFactory
{
IUser CreateUser();
}
SqlServerFactory类,实现IFactory接口
class SqlServerFactory:IFactory
{
public IUser CreateUser()
{
return new sqlserverUser();
}
}
AccessFactory类,实现IFactory接口,实例化AccessUser
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
}
客户端代码
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();
}
增加部门表
class Department
{
private int _id;
public int ID
{
get { return _id; }
set { _id=value; }
}
private string _deptName;
public string DeptName
{
get { return _deptName; }
set { _deptName =value;}
}
}
15.4 用了抽象工厂模式的数据访问程序
interface Department
{
void Insert(Department department);
Department GetDepartment(int id);
}
SqlserverDepartment类
class SqlserverDepartment : IDepartment
{
public void Insert(Department department)
{
……..
}
public Department GetDepartment(int id)
{
……
return nill;
}
}
AccessDepartment类类似
IFactory接口,定义一个创建访问Department表对象的抽象的工厂接口。
interface IFactory
{
IUser CreateUser();
IDepartment CreateDepartment();
}
SqlServerFactory类
class SqlServerFactory : IFactory
{
public IIUser CreateUser()
{
return new SqlserverUser();
}
public IDepartment CreateDepartment()
{
return new SqlserverDepartment();
}
}
AccessFactory类类似
客户端代码:
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
//只需要确定实例化哪一个数据库访问对象给factory
//IFactory factory = new SqlServerFactory();
IFactory factory = new AccessFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
Department id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1)
Console.Read();
}
15.5 抽象工厂模式
抽象工厂模式 Abstract Factory,提供了一个创建一系列相关或相互依赖对象的接口,而无需制定它们具体的类。
“AbstractProductA和AbstractProductB是两个抽象产品,ProductA1和ProductA2、ProductB以及ProductB2就是对两个抽象产品的具体分类的实现。
IFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。ConcreteFactory1和ConcreteFactory2就是两个具体的工厂。
通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂在创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。
15.6 抽象工厂模式的优点和缺点
最大的好处是易于交换产品系列,由于具体工厂类在一个应用中,只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,他只需要改变具体工厂既可以使用不同的产品配置。
第二大好处是:
他让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现费力,不会出现在客户端代码中。
15.7 用简单工厂来改进抽象工厂
class DataAccess
{
//数据库名称,可替换成Access
private static readonly string db = “Sqlserver”;
//private static readonly string db = “Access”;
public static IUser CreateUser()
{
IUser result = nil;
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(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();
}
15.8 用反射+抽象工厂的数据访问程序
类似于OC中的运行时技术
15.9用反射+配置文件实现数据访问程序
在所有使用简单工厂的地方,都可以考虑使用反射技术来去除switch和if,解除分支带来的耦合。