C++设计模式-李建忠
09-Abstract Factory 抽象工厂
1. 对象创建”模式
通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。
- 典型模式
- Factory Method
- Abstract Factory
- Prototype
- Builder
2. 动机(Motivation)
在软件系统中,经常面临着 “一系列相互依赖的对象” 的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?
3. 模式定义
提供一个接口,让该接口负责创建一系列 “相关或者相互依赖的对象” ,无需指定它们具体的类。——《设计模式》GoF
4. 结构(Structure)
5. C++伪代码
class EmployeeDAO
{
public:
vector<EmployeeDO> GetEmployees()
{
//连接数据库
SqlConnection *connection =
new SqlConnection();
connection->ConnectionString = "...";
//执行SQL语句
SqlCommand *command =
new SqlCommand();
command->CommandText = "...";
command->SetConnection(connection); //关联性
//读取执行结果
SqlDataReader *reader = command->ExecuteReader(); //关联性
while (reader->Read())
{
}
}
};
6. C++伪代码改进(版本1 - Factory Method)
//--------------------------------------------------//
class IDBConnection{};
class IDBConnectionFactory
{
public:
virtual IDBConnection *CreateDBConnection() = 0;
};
class SqlConnection : public IDBConnection{}; //支持SQL Server
class SqlConnectionFactory : public IDBConnectionFactory{}; //支持SQL Server的factory
class OracleConnection : public IDBConnection{}; //支持Oracle
//--------------------------------------------------//
class IDBCommand{};
class IDBCommandFactory
{
public:
virtual IDBCommand *CreateDBCommand() = 0;
};
class SqlCommand : public IDBCommand{}; //支持SQL Server
class SqlCommandFactory : public IDBCommandFactory{};
class OracleCommand : public IDBCommand{}; //支持Oracle
//--------------------------------------------------//
class IDataReader{};
class IDataReaderFactory
{
public:
virtual IDataReader *CreateDataReader() = 0;
};
class SqlDataReader : public IDataReader{}; //支持SQL Server
class SqlDataReaderFactory : public IDataReaderFactory{};
class OracleDataReader : public IDataReader{}; //支持Oracle
//--------------------------------------------------//
class EmployeeDAO
{
IDBConnectionFactory *dbConnectionFactory;
IDBCommandFactory *dbCommandFactory;
IDataReaderFactory *dataReaderFactory;
public:
vector<EmployeeDO> GetEmployees()
{
IDBConnection *connection =
dbConnectionFactory->CreateDBConnection();
connection->ConnectionString("...");
IDBCommand *command =
dbCommandFactory->CreateDBCommand();
command->CommandText("...");
command->SetConnection(connection); //关联性
IDBDataReader *reader = command->ExecuteReader(); //关联性
while (reader->Read())
{
}
}
};
如果用户不小心把 mysql的connection 和 oracle的command 混搭在一起,那将会出错!
所以要把这些有关系的 一系列 操作,封装到一起,这就是 Abstract Factory的思想,代码如下:
7. C++伪代码改进(版本2 - Abstract Factory)
//-----------------------------------------------------------//
//数据库访问有关的基类
class IDB
{
DBConnection();
DBCommand();
DataReader();
};
class IDBFactory
{
public:
virtual IDBConnection *CreateDBConnection() = 0;
virtual IDBCommand *CreateDBCommand() = 0;
virtual IDataReader *CreateDataReader() = 0;
};
//支持SQL Server
class SqlDBFactory : public IDBFactory
{
public:
virtual IDBConnection *CreateDBConnection() = 0;
virtual IDBCommand *CreateDBCommand() = 0;
virtual IDataReader *CreateDataReader() = 0;
};
//支持Oracle
class OracleDBFactory : public IDBFactory
{
public:
virtual IDBConnection *CreateDBConnection() = 0;
virtual IDBCommand *CreateDBCommand() = 0;
virtual IDataReader *CreateDataReader() = 0;
};
class EmployeeDAO
{
IDBFactory *dbFactory;
public:
vector<EmployeeDO> GetEmployees()
{
//连接数据库
IDBConnection *connection =
dbFactory->CreateDBConnection();
connection->ConnectionString("...");
//执行SQL语句
IDBCommand *command =
dbFactory->CreateDBCommand();
command->CommandText("...");
command->SetConnection(connection); //关联性
//读取执行结果
IDBDataReader *reader = command->ExecuteReader(); //关联性
while (reader->Read())
{
}
}
};
//-----------------------------------------------------------//
8. 要点总结
如果没有应对 “多系列对象构建” 的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
“系列对象” 指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
Abstract Factory模式主要在于应对“新系列”的需求变动(如:增加一个系列)。其缺点在于难以应对“新对象”的需求变动(对一个系列的基类进行更改)。
8. 要点总结
如果没有应对 “多系列对象构建” 的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
“系列对象” 指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
Abstract Factory模式主要在于应对“新系列”的需求变动(如:增加一个系列)。其缺点在于难以应对“新对象”的需求变动(对一个系列的基类进行更改)。