抽象工厂模式
动机
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在更多系列对象的创建工作。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作” 的紧耦合?
解决方法
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
例子
数据库连接:
class EmployeeDAO
{
public:
vector<EmployeeDO> GetEmployees()
{
SqlConnection *connection = new SqlConnection();
connection->ConnectionString = "...";
SqlCommand *command = new SqlCommand();
command->CommandText = "...";
command->SetConnection(connection);
SqlDataReader *reader = command->ExecuteReader();
while (reader->Read())
{
...
}
}
};
改进(使用工厂模式):
// 数据库访问有关的基类
class IDBConnection
{
};
class IDBConnectionFactory
{
public:
virtual IDBConnection* CreateDBConnection() = 0;
};
class IDBCommand
{
};
class IDBCommandFactory
{
public:
virtual IDBCommand* CreateDBCommand() = 0;
};
class IDataReader
{
};
class IDataReaderFactory
{
public:
virtual IDataReader* CreateDataReader() = 0;
};
// 支持SQL Server
class SqlConnection: public IDBConnection
{
};
class SqlConnectionFactory: public IDBConnectionFactory
{
};
class SqlCommand: public IDBCommand
{
};
class SqlCommandFactory: public IDBCommandFactory
{
};
class SqlDataReader: public IDataReader
{
};
class SqlDataReaderFactory: public IDataReaderFactory
{
};
// 支持Oracle
class OracleConnection: public IDBConnection
{
};
class OracleCommand: public IDBCommand
{
};
class OracleDataReader: public IDataReader
{
};
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())
{
}
}
};
改进(使用抽象工厂模式):
// 数据库访问有关的基类
class IDBConnection
{
};
class IDBCommand
{
};
class IDataReader
{
};
// 抽象工厂
class IDBFactory
{
public:
virtual IDBConnection* CreateDBConnection() = 0;
virtual IDBCommand* CreateDBCommand() = 0;
virtual IDataReader* CreateDataReader() = 0;
};
// 支持SQL Server
class SqlConnection: public IDBConnection
{
};
class SqlCommand: public IDBCommand
{
};
class SqlDataReader: public IDataReader
{
};
class SqlDBFactory: public IDBFactory
{
public:
virtual IDBConnection* CreateDBConnection() = 0;
virtual IDBCommand* CreateDBCommand() = 0;
virtual IDataReader* CreateDataReader() = 0;
};
// 支持Oracle
class OracleConnection: public IDBConnection
{
};
class OracleCommand: public IDBCommand
{
};
class OracleDataReader: public IDataReader
{
};
class EmployeeDAO
{
IDBFactory *dbFactory;
public:
vector<EmployeeDO> GetEmployees()
{
IDBConnection *connection = dbFactory->CreateDBConnection();
connection->ConnectionString("...");
IDBCommand *command = dbFactory->CreateDBCommand();
command->CommandText("...");
command->SetConnection(connection); // 关联性
IDBDataReader *reader = command->ExecuteReader(); // 关联性
while (reader->Read())
{
}
}
};
优缺点
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。