转载出处:http://beniao.cnblogs.com/
一、模式描述
我的程序中有需要一系列的对象,比如我们要吃一碗米饭(Rice),要喝一杯咖啡(Coffee)......,要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活。那么我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象呢?
这当然是可以的,根据GOF在《设计模式》一书里介绍,要创建对象这样的工作应该是属于创建型模式完成的。熟悉各种设计模式意图的朋友就会很快得出结论:“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类”,至少“无需指定它们具体的类”符合我们的要求。OK,这就是抽象工厂模式的意图。
二、模式意图
提供一个创建一系列相关或相互依赖对象的接口,而不需指定他们具体的类。
三、模式UML图:
四、模式参与者
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
五、模式与反射
利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,C# 中的反射机制便是一个很重要的工具,好好地利用就可以在实际中发挥很大的作用。
反射是.NET Framework中的一个非常重要的特性。相信绝大多数的朋友都对其有所了解或是已经熟练的应用这项技术。我们需要根据需求去动态的创建一对象的实例,在程序设计中,通常我们会为了解耦合,把接口的实现对象写入配置文件,让工厂自己去一个特定的地方(配置文件)找他应该要实例化的对象(接口的实现对象),通过这样来实现“依赖注入(Dependency Injection)”。
本来“依赖注入”需要专门的IOC容器提供,比如Spring.net,Castle这类似的框架产品。而在抽象工厂模式的应用中显然没有这么麻烦,通常的实现就是使用.NET技术‘反射’就可以了。下面是反射的两种常见应用:
应用一:
Activator.CreateInstance("类型");
应用二:
Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");
六、抽象工厂的简单实现
1
namespace DesignPattern.AbstractFactory2


{3
public class User4

{5
private int _id;6
public int Id7

{8

get
{ return _id; }9

set
{ _id = value; }10
}11

12
private string _name;13
public string Name14

{15

get
{ return _name; }16

set
{ _name = value; }17
}18

19
private string _age;20
public string Age21

{22

get
{ return _age; }23

set
{ _age = value; }24
}25

26
public User()27

{ }28

29
public User(int id, string name, string age)30

{31
_id = id;32
_name = name;33
_age = age;34
}35
}36
}37
----------------------------------------------------------------------38
namespace DesignPattern.AbstractFactory39


{40
public class News41

{42
private int _id;43
public int Id44

{45

get
{ return _id; }46

set
{ _id = value; }47
}48

49
private string _title;50
public string Title51

{52

get
{ return _title; }53

set
{ _title = value; }54
}55

56
private string _context;57
public string Context58

{59

get
{ return _context; }60

set
{ _context = value; }61
}62

63
private string _author;64
public string Author65

{66

get
{ return _author; }67

set
{ _author = value; }68
}69

70
public News()71

{ }72

73
public News(int id, string title, string context, string author)74

{75
_id = id;76
_title = title;77
_context = context;78
_author = author;79
}80
}81
}82
namespace
DesignPattern.AbstractFactory2

{3

/**//// <summary>4
/// 抽象产品角色5
/// </summary>6
public interface INews7

{8
void Insert(News news);9
News QueryById(int newsId);10
}11

12

/**//// <summary>13
/// 具体产品角色14
/// </summary>15
public class NewsSql:INews16

{17
public void Insert(News news)18

{19
Console.WriteLine("插入新闻到SQL数据库");20
}21

22
public News QueryById(int newsId)23

{24
return new News(1, "Hello", " Hello C#!", "beniao");25
}26
}27

28

/**//// <summary>29
/// 具体产品角色30
/// </summary>31
public class NewsAccess : INews32

{33
public void Insert(News news)34

{35
Console.WriteLine("插入新闻到Access数据库");36
}37

38
public News QueryById(int newsId)39

{40
return new News(1, "Hello", " Hello C#!", "beniao");41
}42
}43
}
namespace
DesignPattern.AbstractFactory2

{3

/**//// <summary>4
/// 抽象产品角色5
/// </summary>6
public interface IUser7

{8
void Insert(User user);9
User QueryById(int userId);10
}11

12

/**//// <summary>13
/// 具体产品角色14
/// </summary>15
public class UserSql:IUser16

{17
public void Insert(User user)18

{19
Console.WriteLine("Insert SQL OK!");20
}21

22
public User QueryById(int userId)23

{24
return new User(1, "beniao", "22");25
}26
}27

28

/**//// <summary>29
/// 具体产品角色30
/// </summary>31
public class UserAccess : IUser32

{33
public void Insert(User user)34

{35
Console.WriteLine("Insert Access OK!");36
}37

38
public User QueryById(int userId)39

{40
return new User(2, "beniao", "23");41
}42
}43
}
namespace
DesignPattern.AbstractFactory2

{3

/**//// <summary>4
/// 工厂角色(根据配置文件来确定创建何种对象)5
/// </summary>6
public class DataAccess7

{8
public static IUser CreateUser()9

{10
string obj = ConfigurationManager.AppSettings["usersql"];11
return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);12
}13

14
public static INews CreateNews()15

{16
string obj = ConfigurationManager.AppSettings["newssql"];17
return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);18
}19
}20
***********************************************************************************21

/**//// <summary>22
/// 如果根据GOF的定义及UML图,此为抽象工厂角色23
/// </summary>24
public class Factory25

{26
public virtual IUser CreateUser() 27

{28
return null;29
}30

31
public virtual INews CreateNews()32

{33
return null;34
}35
}36

37

/**//// <summary>38
/// 具体的工厂角色39
/// </summary>40
public class SqlFactory:Factory41

{42
public override IUser CreateUser()43

{44
string obj = ConfigurationManager.AppSettings["usersql"];45
return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);46
}47

48
public override INews CreateNews()49

{50
string obj = ConfigurationManager.AppSettings["newssql"];51
return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);52
}53
}54

55

/**//// <summary>56
/// 具体的工厂角色57
/// </summary>58
public class AccessFactory : Factory59

{60
public override IUser CreateUser()61

{62
string obj = ConfigurationManager.AppSettings["useracc"];63
return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);64
}65

66
public override INews CreateNews()67

{68
string obj = ConfigurationManager.AppSettings["newsacc"];69
return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);70
} 71
}72
}
namespace
DesignPattern.AbstractFactory2

{3
class Program4

{5
static void Main(string[] args)6

{7
IUser user = DataAccess.CreateUser();8
user.Insert(null);9

10
INews news = DataAccess.CreateNews();11
news.Insert(null);12

13
//******************GOF************************14

15
Factory factory = new SqlFactory();16
factory.CreateNews().Insert(null);17
factory.CreateUser().Insert(null);18

19
factory = new AccessFactory();20
factory.CreateNews().Insert(null);21
factory.CreateUser().Insert(null);22
}23
}24
}
七、.NET 2.0中的抽象工厂模式
.NET 2.0相比.NET 1.1有很大的改进,就在ADO.NET上来说吧,提供了一套新的操作接口。下面我就简单的介绍下这套接口的设计,在System.Date下提供了IDbConnection 、IDbCommand、IDbDataAdapter以及IDbTransaction这样一系列接口,通过ProviderFactory来完成具体实现对象的创建,这里就是抽象工厂模式的一个应用。示意性代码:
public
IDbConnection CreateConnection()2

{3
IDbConnection conn = null;4
try5

{6
conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider]);7
}8
catch(TargetInvocationException e)9

{10
throw new Exception(e.Message);11
}12
return conn;13
}
14

15
public
IDbConnection CreateConnection(
string
connectionString)16

{17
IDbConnection conn = null;18

object[] param =
{ connectionString };19
try20

{21
conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider], param);22
}23
catch (TargetInvocationException e)24

{25
throw new Exception(e.Message);26
}27
return conn;28
}
在_connectionTypes数组里存放的是IDbConnection接口的具体实现类型,如下:
private
static
Type[] _connectionTypes
=
new
Type[]
{ typeof(OleDbConnection), typeof(SqlConnection) }
;
由于Command,DataAdapter等对象的代码都和上面很相似,这里就不作过多解释,我把代码贴到下面,有兴趣的看看:
1
using System;2
using System.Data;3
using System.Configuration;4
using System.Web;5
using System.Web.Security;6
using System.Web.UI;7
using System.Web.UI.WebControls;8
using System.Web.UI.WebControls.WebParts;9
using System.Web.UI.HtmlControls;10
using System.Reflection;11
using System.Data.OleDb;12
using System.Data.SqlClient;13

14

/**//// <summary>15
/// ProviderFactory 的摘要说明16
/// </summary>17
public class ProviderFactory18


{19

/**//// <summary>20
/// 私有构造器,伪单例。21
/// 一个具体的工厂通常是一个单件(Singleton)。22
/// </summary>23
private ProviderFactory()24

{25

26
}27

28
public ProviderFactory(ProviderType provider)29

{30
_provider = provider;31
}32

33

private static Type[] _connectionTypes = new Type[]
{ typeof(OleDbConnection), typeof(SqlConnection) };34

private static Type[] _commandTypes = new Type[]
{ typeof(OleDbCommand), typeof(SqlCommand) };35

private static Type[] _dataAdapterTypes = new Type[]
{ typeof(OleDbDataAdapter), typeof(SqlDataAdapter) };36

private static Type[] _dataParameterTypes = new Type[]
{ typeof(OleDbParameter), typeof(SqlParameter) };37
38
private ProviderType _provider;39
public ProviderType Provider40

{41

get
{ return _provider; }42

set
{ _provider = value; }43
}44

45
public IDbConnection CreateConnection()46

{47
IDbConnection conn = null;48
try49

{50
conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider]);51
}52
catch(TargetInvocationException e)53

{54
throw new Exception(e.Message);55
}56
return conn;57
}58

59
public IDbConnection CreateConnection(string connectionString)60

{61
IDbConnection conn = null;62

object[] param =
{ connectionString };63
try64

{65
conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider], param);66
}67
catch (TargetInvocationException e)68

{69
throw new Exception(e.Message);70
}71
return conn;72
}73

74
public IDbCommand CreateCommand()75

{76
IDbCommand cmd = null;77
try78

{79
cmd = (IDbCommand)Activator.CreateInstance(_commandTypes[(int)_provider]);80
}81
catch (TargetInvocationException e)82

{83
throw new Exception(e.Message);84
}85
return cmd;86
}87

88
public IDbCommand CreateCommand(string cmdText)89

{90
IDbCommand cmd = null;91

object[] args =
{ cmdText };92
try93

{94
cmd = (IDbCommand)Activator.CreateInstance(_commandTypes[(int)_provider], args);95
}96
catch (TargetInvocationException e)97

{98
throw new Exception(e.Message);99
}100
return cmd;101
}102

103
public IDbCommand CreateCommand(string cmdText, IDbConnection connection)104

{105
IDbCommand cmd = null;106

object[] args =
{ cmdText, connection };107
try108

{109
cmd = (IDbCommand)Activator.CreateInstance(_commandTypes[(int)_provider], args);110
}111
catch (TargetInvocationException e)112

{113
throw new Exception(e.Message);114
}115
return cmd;116
}117

118
public IDbCommand CreateCommand(string cmdText, IDbConnection connection, IDbTransaction transaction)119

{120
IDbCommand cmd = null;121

object[] args =
{ cmdText, connection, transaction };122
try123

{124
cmd = (IDbCommand)Activator.CreateInstance(_commandTypes[(int)_provider], args);125
}126
catch (TargetInvocationException e)127

{128
throw new Exception(e.Message);129
}130
return cmd;131
}132

133
public IDbDataAdapter CreateDataAdapter()134

{135
IDbDataAdapter da = null;136
try137

{138
da = (IDbDataAdapter)Activator.CreateInstance(_dataAdapterTypes[(int)_provider]);139
}140
catch (TargetInvocationException e)141

{142
throw new SystemException(e.InnerException.Message, e.InnerException);143
}144
return da;145
}146

147
public IDbDataAdapter CreateDataAdapter(IDbCommand selectCommand)148

{149
IDbDataAdapter da = null;150

object[] args =
{ selectCommand };151
try152

{153
da = (IDbDataAdapter)Activator.CreateInstance(_dataAdapterTypes[(int)_provider], args);154
}155
catch (TargetInvocationException e)156

{157
throw new SystemException(e.InnerException.Message, e.InnerException);158
}159
return da;160
}161

162
public IDbDataAdapter CreateDataAdapter(string selectCommandText, IDbConnection selectConnection)163

{164
IDbDataAdapter da = null;165

object[] args =
{ selectCommandText, selectConnection };166
try167

{168
da = (IDbDataAdapter)Activator.CreateInstance(_dataAdapterTypes[(int)_provider], args);169
}170
catch (TargetInvocationException e)171

{172
throw new SystemException(e.InnerException.Message, e.InnerException);173
}174
return da;175
}176

177
public IDbDataAdapter CreateDataAdapter(string selectCommandText, string selectConnectionString)178

{179
IDbDataAdapter da = null;180

object[] args =
{ selectCommandText, selectConnectionString };181
try182

{183
da = (IDbDataAdapter)Activator.CreateInstance(_dataAdapterTypes[(int)_provider], args);184
}185
catch (TargetInvocationException e)186

{187
throw new SystemException(e.InnerException.Message, e.InnerException);188
}189
return da;190
}191

192
public IDbDataParameter CreateDataParameter()193

{194
IDbDataParameter param = null;195
try196

{197
param = (IDbDataParameter)Activator.CreateInstance(_dataParameterTypes[(int)_provider]);198
}199
catch (TargetInvocationException e)200

{201
throw new SystemException(e.InnerException.Message, e.InnerException);202
}203
return param;204
}205

206
public IDbDataParameter CreateDataParameter(string parameterName, object value)207

{208
IDbDataParameter param = null;209

object[] args =
{ parameterName, value };210
try211

{212
param = (IDbDataParameter)Activator.CreateInstance(_dataParameterTypes[(int)_provider], args);213
}214
catch (TargetInvocationException e)215

{216
throw new SystemException(e.InnerException.Message, e.InnerException);217
}218
return param;219
}220

221
public IDbDataParameter CreateDataParameter(string parameterName, DbType dataType)222

{223
IDbDataParameter param = CreateDataParameter();224
if (param != null)225

{226
param.ParameterName = parameterName;227
param.DbType = dataType;228
}229
return param;230
}231

232
public IDbDataParameter CreateDataParameter(string parameterName, DbType dataType, int size)233

{234
IDbDataParameter param = CreateDataParameter();235
if (param != null)236

{237
param.ParameterName = parameterName;238
param.DbType = dataType;239
param.Size = size;240
}241
return param;242
}243

244
public IDbDataParameter CreateDataParameter(string parameterName, DbType dataType, int size, string sourceColumn)245

{246
IDbDataParameter param = CreateDataParameter();247
if (param != null)248

{249
param.ParameterName = parameterName;250
param.DbType = dataType;251
param.Size = size;252
param.SourceColumn = sourceColumn;253
}254
return param;255
}256
}257
关于.NET 2.0的这一知识点不了解的朋友可以下载Web Cast课程进行学习。本文就简单的介绍这些。
七、.NET 2.0中的新ADO.NET操作接口应用示例
建立一ASP.NET网站项目,在默认的Default.aspx里放置一个GridView控件便OK。这里以MSSQL 2000里的Northwind数据库作为示例数据库,查询出订单表的数据呈现在aspx页面上,进入后台代码文件(.cs文件):
public
partial
class
_Default : System.Web.UI.Page 2

{3
protected void Page_Load(object sender, EventArgs e)4

{5
string connectionString="Data Source=.;Initial Catalog=Northwind;user id=sa;password=;";6
string cmdText = "select * from orders";7

8
ProviderFactory factory = new ProviderFactory(ProviderType.SqlClient);9
IDbConnection conn = factory.CreateConnection(connectionString);10
IDbDataAdapter sda = factory.CreateDataAdapter(cmdText, conn);11
DataSet ds = new DataSet();12
sda.Fill(ds);13
this.GridView1.DataSource = ds.Tables[0];14
this.GridView1.DataBind();15
}16
}
ProviderFactory担任着工厂的角色,负责创建如IDbConnection、IDbCommand等一系列的产品。如上,我们拿到了工厂角色,通过工厂角色的CreateConnection就创建到了一个基于抽象产品角色IDbConnection接口的实现对象(具体是什么实现对象我们暂不管)。
.NET 2.0提供了这一套操作接口,对于程序实现上就更加灵活了,更是强调了使用“依赖接口/抽象编程”的思想。
示例程序代码下载
本文介绍了抽象工厂模式的概念及其在.NET Framework中的应用,通过示例代码展示了如何利用反射技术创建一系列相关对象,同时探讨了该模式在.NET 2.0 ADO.NET操作接口中的实现。
679

被折叠的 条评论
为什么被折叠?



