C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】
2021-05-11 01:26
标签:2.3 adapter gets 集中 客户端 数据库连接 怎么办 create 添加 一、引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力。今天我要写第四个模式了,该模式叫抽象工厂。上一篇文章我们讲了【工厂方法】模式,它是为了解决【简单工厂】模式所面对的问题,它的问题就是:如果我们增加新的产品,工厂类的方法就要修改本身的代码,增加产品越多,其逻辑越复杂,同时这样的修改也是不符合【开放关闭原则OCP】,对修改代码关闭,对增加代码开放。为了解决【简单工厂】的问题,我们引出了【工厂方法】模式,通过子类化工厂类,解决了工厂类责任的划分,产品和相应的工厂一一对应,符合了OCP。如果我们要设计一套房子,当然我们知道房子是由房顶、地板、窗户、房门组成的,别的组件暂时省略,先设计一套古典风格的房子,再创建一套现代风格的房子,再创建一套欧式风格的房子,这么多套房子,我们该怎么办呢?今天我们要讲的【抽象工厂】模式可以很好的解决多套变化的问题。 二、抽象工厂详细介绍 2.1、动机(Motivate): 在软件系统中,经常面临着"一系统相互依赖的对象"的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种"封装机制"来避免客户程序和这种"多系列具体对象创建工作"的紧耦合? 2.2、意图(Intent): 2.3、结构图(Struct) 2.4、抽象工厂的具体实现 随着我们年龄的增大,我们也到了结婚的年龄。结婚首要的问题就是房子的问题,假设我有一个很有钱的爸爸,哈哈,有钱可以解决很多问题。作为长子的我,希望能有一套欧式风格的房子,再加上田园风光,此生足矣。我弟弟就不一样了,他想要一套现代样式的房子,如果兄弟姊妹再多年一点,那就有更多的要求了。由于房子由房顶、地板、窗户和房门组成,其他组件暂时省略,有这么多套房子要建设,每套房子的房顶、地板、窗户和房门都是一个体系的,那就让我们看看如何使用【抽象工厂】模式来实现不同房屋的建造。 让我们看看该模式如何应对需求的变化,假设我的表弟一看我们的房子很好,他也想要一套古典风格的房子(哈哈,这个家伙事挺多的,有好事总是落不下他)。 三、抽象工厂的优缺点 优点:【抽象工厂】模式将系列产品的创建工作延迟到具体工厂的子类中,我们声明工厂类变量的时候是使用的抽象类型,同理,我们使用产品类型也是抽象类型,这样做就尽可能的可以减少客户端代码与具体产品类之间的依赖,从而降低了系统的耦合度。耦合度降低了,对于后期的维护和扩展就更有利,这也就是【抽象工厂】模式的优点所在。可能有人会说在Main方法里面(这里的代码就是客户端的使用方)还是会使用具体的工厂类,对的。这个其实我们通过Net的配置,把这部分移出去,最后把依赖关系放到配置文件中。如果有新的需求我们只需要修改配置文件,根本就不需要修改代码了,让客户代码更稳定。依赖关系肯定会存在,我们要做的就是降低依赖,想完全去除很难,也不现实。 缺点:有优点肯定就有缺点,因为每种模式都有他的使用范围,或者说要解决的问题,不能解决的问题就是缺点了,其实也不能叫缺点了。【抽象工厂】模式很难支持增加新产品的变化,这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。 使用场景: 如果系统需要多套的代码解决方案,并且每套的代码方案中又有很多相互关联的产品类型,并且在系统中我们可以相互替换的使用一套产品的时候可以使用该模式,客户端不需要依赖具体实现。 四、.NET中抽象工厂模式实现 微软的类库发展了这么多年,设计模式在里面有大量的应用,【抽象工厂】模式在.NET类库中也存在着大量的使用,比如和操作数据库有关的类型,这个类就是System.Data.Common.DbProviderFactory,这个类位于System.Data.dll程序集中。该类扮演抽象工厂模式中抽象工厂的角色,我们可以用ILSpy反编译工具查看该类的实现: /// 扮演抽象工厂的角色 SqlClientFactory扮演着具体工厂的角色,用来创建连接SQL Server数据所需要的对象 OdbcFactory也是具体工厂类 当然,我们也有OleDbFactory 类型,都是负责具体的数据库操作。DbProviderFactory就是【抽象工厂】模式UML里面AbstractFactory类型。其他具体的工厂类型继承DbProviderFactory类型,这个结构很简单,我就不画图了。 五、总结 终于写完了,写了3个小时,学习设计模式不能死学,要把握关键电。关键点第一是,面向对象设计模式的基本原则,有了原则,考虑问题就不会跑偏,然后再仔细把握每种模式的使用场景和要解决的问题,多写写代码,多看看Net的类库,它是最好的教材。 C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】 标签:2.3 adapter gets 集中 客户端 数据库连接 怎么办 create 添加 原文地址:http://www.cnblogs.com/PatrickLiu/p/7596897.html
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
该图是抽象工厂的UML图,结合抽象工厂的意图、动机和图示来理解该模式,今天我们就以建设房子为例来说明抽象工厂的实现机理。 1 ///
2.5、 抽象工厂应对需求变更 1 ///
此时,只需要添加五个类:一个是古典风格工厂类,负责创建古典风格的房子,另外几个类是具有古典风格的房顶、地板、窗户和房门的具体产品。从上面代码看出,抽象工厂对于系列产品的变化支持 “开放——封闭”原则(指的是要求系统对扩展开放,对修改封闭),扩展起来非常简便,但是,抽象工厂对于增加新产品这种情况就不支持”开放——封闭 “原则,因为要修改创建系列产品的抽象基类AbstractFactory,增加相应产品的创建方法,这也是抽象工厂的缺点所在。
/// 创建连接数据库时所需要的对象集合,
/// 这个对象集合包括有 DbConnection对象(这个是抽象产品类,如绝味例子中的YaBo类)、DbCommand类、DbDataAdapter类,针对不同的具体工厂都需要实现该抽象类中方法, 1 public abstract class DbProviderFactory
2 {
3 public virtual bool CanCreateDataSourceEnumerator
4 {
5 get
6 {
7 return false;
8 }
9 }
10
11 public virtual DbCommand CreateCommand()
12 {
13 return null;
14 }
15
16 public virtual DbCommandBuilder CreateCommandBuilder()
17 {
18 return null;
19 }
20
21 public virtual DbConnection CreateConnection()
22 {
23 return null;
24 }
25
26 public virtual DbConnectionStringBuilder CreateConnectionStringBuilder()
27 {
28 return null;
29 }
30
31 public virtual DbDataAdapter CreateDataAdapter()
32 {
33 return null;
34 }
35
36 public virtual DbParameter CreateParameter()
37 {
38 return null;
39 }
40
41 public virtual CodeAccessPermission CreatePermission(PermissionState state)
42 {
43 return null;
44 }
45
46 public virtual DbDataSourceEnumerator CreateDataSourceEnumerator()
47 {
48 return null;
49 }
50 }
51 }
DbProviderFactory类是一个抽象工厂类,该类提供了创建数据库连接时所需要的对象集合的接口,实际创建的工作在其子类工厂中进行,微软使用的是SQL Server数据库,因此提供了连接SQL Server数据的具体工厂实现,具体代码可以用反编译工具查看,具体代码如下: 1 public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
2 {
3 public static readonly SqlClientFactory Instance = new SqlClientFactory();
4
5 public override bool CanCreateDataSourceEnumerator
6 {
7 get
8 {
9 return true;
10 }
11 }
12
13 private SqlClientFactory()
14 {
15 }
16
17 public override DbCommand CreateCommand()
18 {
19 return new SqlCommand();
20 }
21
22 public override DbCommandBuilder CreateCommandBuilder()
23 {
24 return new SqlCommandBuilder();
25 }
26
27 public override DbConnection CreateConnection()
28 {
29 return new SqlConnection();
30 }
31
32 public override DbConnectionStringBuilder CreateConnectionStringBuilder()
33 {
34 return new SqlConnectionStringBuilder();
35 }
36
37 public override DbDataAdapter CreateDataAdapter()
38 {
39 return new SqlDataAdapter();
40 }
41
42 public override DbParameter CreateParameter()
43 {
44 return new SqlParameter();
45 }
46
47 public override CodeAccessPermission CreatePermission(PermissionState state)
48 {
49 return new SqlClientPermission(state);
50 }
51
52 public override DbDataSourceEnumerator CreateDataSourceEnumerator()
53 {
54 return SqlDataSourceEnumerator.Instance;
55 }
56
57 object IServiceProvider.GetService(Type serviceType)
58 {
59 object result = null;
60 if (serviceType == GreenMethods.SystemDataCommonDbProviderServices_Type)
61 {
62 result = GreenMethods.SystemDataSqlClientSqlProviderServices_Instance();
63 }
64 return result;
65 }
66 }
1 public sealed class OdbcFactory : DbProviderFactory
2 {
3 public static readonly OdbcFactory Instance = new OdbcFactory();
4
5 private OdbcFactory()
6 {
7 }
8
9 public override DbCommand CreateCommand()
10 {
11 return new OdbcCommand();
12 }
13
14 public override DbCommandBuilder CreateCommandBuilder()
15 {
16 return new OdbcCommandBuilder();
17 }
18
19 public override DbConnection CreateConnection()
20 {
21 return new OdbcConnection();
22 }
23
24 public override DbConnectionStringBuilder CreateConnectionStringBuilder()
25 {
26 return new OdbcConnectionStringBuilder();
27 }
28
29 public override DbDataAdapter CreateDataAdapter()
30 {
31 return new OdbcDataAdapter();
32 }
33
34 public override DbParameter CreateParameter()
35 {
36 return new OdbcParameter();
37 }
38
39 public override CodeAccessPermission CreatePermission(PermissionState state)
40 {
41 return new OdbcPermission(state);
42 }
43 }
文章标题:C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】
文章链接:http://soscw.com/index.php/essay/84186.html