抽象工厂模式(Abstract Factory)

First Post:

Last Update:

抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory),提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式结构图

略,用途较少,缺点很多

抽象工厂的优点

最大的优点是:易于交互产品系列,由于具体工厂类,在一个应用中只需要在初始化时出现一次,这使得改变一个应用的具体工厂非常容易,它只需要改变具体工厂即可使用不同的产品配置。如果需要更改数据库访问,只需要更改具体工厂即可。

第二:它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。(客户端只需要认识IUser和IDepartment,即数据操作的抽象接口即可)

抽象工厂的缺点

缺点是显而易见的,如果需求的更改来自于增加功能,如增加项目表

我们就需要多写IProject、SqlServerProject、AccessProject三个类。

还要更改IFactory、SqlServerFactory、AccessFactory。非常糟糕。

实例——不同的数据库访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
在数据库中的实践,在设计数据库访问底层持久时,需要考虑到底使用哪种数据库,如果一开始没有对此进行设计,碰到更换数据库时,将会是一场灾难。
class Department
{ //... }
interface IDepartment
{
void Insert(Department department);

Department GetDepartment(int id);
}
//用于访问sqlserver的Department表
class SqlSeverDepartment : IDepartment
{
public Department GetDepartment(int id)
{
return null;
}

public void Insert(Department department)
{
//SqlSever向Department表插入一条数据
}
}
//用于访问Access的Department表
class AccessDepartment : IDepartment
{
public Department GetDepartment(int id)
{
return null;
}

public void Insert(Department department)
{
//Access向Department表插入一条数据
}
}

interface IFactory
{
IUser CreateUser();

IDepartment CreateDepartment();
}


class SqlServerFactory : IFactory
{
public IDepartment CreateDepartment()
{
//实例化Sqlserver对应的部门类
return new SqlSeverDepartment();
throw new NotImplementedException();
}

public IUser CreateUser()
{
//实例化Sqlserver对应的用户类
return new SqlServerUser();
throw new NotImplementedException();
}
}


class AccessFactory : IFactory
{
public IDepartment CreateDepartment()
{
//实例化Access对应的部门类
return new AccessDepartment();
throw new NotImplementedException();
}

public IUser CreateUser()
{
//实例化Access对应的用户类
return new AccessUser();
throw new NotImplementedException();
}
}

//客户端代码
class solution
{
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(dept);
iu.GetUser();

//此时与具体的数据库访问解除了依赖
IDepartment id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
}
}

用简单工厂方式改进抽象工厂模式

去除三个类:IFactory、SqlServerFactory和AccessFactory

取代之用DataAccess类通过简单工厂来实现

改进后的抽象工厂结构图:

改进后的抽象工厂结构图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
代码实现:
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;
}

public static IDepartment CreateDepartment()
{
IDepartment result = null;
switch (db)
{
case "sqlserver":
result = new SqlServerDept();
break;
case "Access":
result = new AccessDept();
break;
}
return result;
}
}

//客户端代码
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);

如果要增加Oracle数据库访问,只需要在DataAccess类中每个方法的switch分支中添加Oracle分支。

抽象工厂模式+反射(+配置)实现数据访问