首页 > 代码库 > c++ 设计模式9 (Abstract Factory 抽象工厂模式)

c++ 设计模式9 (Abstract Factory 抽象工厂模式)

5.2 抽象工厂模式

动机:在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。

 

代码示例:

实现利用数据库的业务逻辑,支持多数据库(Sql,Oracle等),有连接、命令、读取等功能。

其中命令,连接功能之间有相互联系。

方法一(使用工厂方法):

每个功能类有一个创建的工厂,如IDBConnection与IDBConnectionFactory

技术分享
 1 //数据库访问有关的基类
 2 class IDBConnection{
 3     
 4 };
 5 class IDBConnectionFactory{
 6 public:
 7     virtual IDBConnection* CreateDBConnection()=0;
 8 };
 9 
10 
11 class IDBCommand{
12     
13 };
14 class IDBCommandFactory{
15 public:
16     virtual IDBCommand* CreateDBCommand()=0;
17 };
18 
19 
20 class IDataReader{
21     
22 };
23 class IDataReaderFactory{
24 public:
25     virtual IDataReader* CreateDataReader()=0;
26 };
27 
28 
29 //支持SQL Server
30 class SqlConnection: public IDBConnection{
31     
32 };
33 class SqlConnectionFactory:public IDBConnectionFactory{
34     
35 };
36 
37 
38 class SqlCommand: public IDBCommand{
39     
40 };
41 class SqlCommandFactory:public IDBCommandFactory{
42     
43 };
44 
45 
46 class SqlDataReader: public IDataReader{
47     
48 };
49 class SqlDataReaderFactory:public IDataReaderFactory{
50     
51 };
52 
53 //支持Oracle
54 class OracleConnection: public IDBConnection{
55     
56 };
57 
58 class OracleCommand: public IDBCommand{
59     
60 };
61 
62 class OracleDataReader: public IDataReader{
63     
64 };
65 
66 
67 
68 class EmployeeDAO{
69     IDBConnectionFactory* dbConnectionFactory;
70     IDBCommandFactory* dbCommandFactory;
71     IDataReaderFactory* dataReaderFactory;
72     
73     
74 public:
75     vector<EmployeeDO> GetEmployees(){
76         IDBConnection* connection =
77             dbConnectionFactory->CreateDBConnection(...);
78         connection->ConnectionString("...");
79 
80         IDBCommand* command =
81             dbCommandFactory->CreateDBCommand(...);
82         command->CommandText("...");
83         command->SetConnection(connection); //关联性
84 
85         IDBDataReader* reader = command->ExecuteReader(); //关联性
86         while (reader->Read()){
87 
88         }
89 
90     }
91 };
技术分享

分析上述代码,虽然解决了组件创建的问题。但是仔细考虑,由于功能之间具有关联性,不同类型数据库的对象并不能同时创建搭配(如sql的command和oracle的connection搭配,显然不合理)。所以考虑抽象工厂模式。见方法二:

使用一个工厂,将一系列相互依赖的的对象创建在一个工厂中实现。

技术分享
 1 //数据库访问有关的基类
 2 class IDBConnection{
 3     
 4 };
 5 
 6 class IDBCommand{
 7     
 8 };
 9 
10 class IDataReader{
11     
12 };
13 
14 
15 class IDBFactory{
16 public:
17     virtual IDBConnection* CreateDBConnection()=0;
18     virtual IDBCommand* CreateDBCommand()=0;
19     virtual IDataReader* CreateDataReader()=0;
20     
21 };
22 
23 
24 //支持SQL Server
25 class SqlConnection: public IDBConnection{
26     
27 };
28 class SqlCommand: public IDBCommand{
29     
30 };
31 class SqlDataReader: public IDataReader{
32     
33 };
34 
35 
36 class SqlDBFactory:public IDBFactory{
37 public:
38     virtual IDBConnection* CreateDBConnection()=0;
39     virtual IDBCommand* CreateDBCommand()=0;
40     virtual IDataReader* CreateDataReader()=0;
41  
42 };
43 
44 //支持Oracle
45 class OracleConnection: public IDBConnection{
46     
47 };
48 
49 class OracleCommand: public IDBCommand{
50     
51 };
52 
53 class OracleDataReader: public IDataReader{
54     
55 };
56 
57 
58 
59 class EmployeeDAO{
60     IDBFactory* dbFactory;
61     
62 public:
63     vector<EmployeeDO> GetEmployees(){
64         IDBConnection* connection =
65             dbFactory->CreateDBConnection();
66         connection->ConnectionString("...");
67 
68         IDBCommand* command =
69             dbFactory->CreateDBCommand();
70         command->CommandText("...");
71         command->SetConnection(connection); //关联性
72 
73         IDBDataReader* reader = command->ExecuteReader(); //关联性
74         while (reader->Read()){
75 
76         }
77 
78     }
79 };
技术分享

 

模式定义:

提供一个接口,让该接口复杂创建一系列”相关或者相互依赖的对象“,无需指定它们具体的类。

类图:

技术分享

要点总结:

如果没有应对”多系列对象构建“的需求变化,则没有必要使用Abstract Factory模式,这是要使用工厂方法即可。

”系列对象“指的是某一特定系列下的对象之间有相互依赖或作用的关系。不同系列的对象之间不能相互依赖。

Abstract Factory模式主要在于应对”新系列“的需求变动。其缺点在于难以应对”新对象“的需求变动。

c++ 设计模式9 (Abstract Factory 抽象工厂模式)