抽象工厂模式Abstract Factory, 解决的是一系列相互依赖对象的创建.
动机
在软件系统中,经常面临着"一系列相互依赖的对象"的创建工作; 同时由于需求的变化,往往存在更多系列对象的创建工作.
抽象工厂,提供一个接口,让该接口负责创建一系列相互依赖对象的创建工作,无需指定他们具体的类.
实例
考虑一个数据库员工数据输出的类,
class EmployeeDataBaseOutput{
public:
vector<Employee> GetAllEmployees() {
SqlConnection* connection = new SqlConnection();
connection->ConnectionString = "...";
SqlCommand* command = new SqlCommand();
command->CommandText = "...";
command->SetConnection(connection);
SqlDataReader* reader = command->ExecuteReader();
while(reader->Read()) {
}
}
};
目前只支持sql数据库的访问操作,考虑对其他数据库访问的支持,我们需要可以考虑继承的方法,定义基类,
class DataBaseConnctionInterface {
};
class DataBaseCommandInterface {
};
class DataBaseDataReaderInterface {
};
class SqlConnection : public DataBaseConnctionInterface {
};
class OracleConnection : public DataBaseConnctionInterface {
};
class SqlCommand:public DataBaseCommandInterface {
};
class OracleCommand : public DataBaseCommandInterface {
};
class SqlDataReader : public DataBaseDataReaderInterface {
};
class OracleDataReader : public DataBaseDataReaderInterface {
};
然后把类EmployeeDataBaseOutput::GetAllEmployees
中的指针全部变为基类的指针.
class EmployeeDataBaseOutput{
public:
vector<Employee> GetAllEmployees() {
DataBaseConnctionInterface* connection = new SqlConnection();
connection->ConnectionString("...");
DataBaseCommandInterface* command = new SqlCommand();
command->CommandText("...");
command->SetConnection(connection);
DataBaseDataReaderInterface* reader = command->ExecuteReader();
while(reader->Read()) {
}
}
};
同时考虑将new
对象的操作替换掉,如果按照工厂模式的做法,需要定义工厂基类,然后派生出生成具体对象的工厂.
class DataBaseConnectionFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() = 0;
~DataBaseConnectionFactoryInterface() { }
};
class SqlConnectionFactory : public DataBaseConnectionFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() {
return new SqlConnection();
}
};
class OracleConnectionFactory : public DataBaseConnectionFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() {
return new OracleConnection();
}
};
class DataBaseCommandFactoryInterface {
public:
virtual DataBaseCommandInterface* CreatDataBaseCommand()=0;
};
class SqlCommnadFactoryFactory : public DataBaseCommandFactoryInterface {
public:
virtual DataBaseCommandInterface* CreatDataBaseCommand() {
return new SqlCommand();
}
};
class OracleCommandFactory : public DataBaseCommandFactoryInterface {
public:
virtual DataBaseCommandInterface* CreatDataBaseCommand() {
return new OracleCommand();
}
};
基于工厂,去掉EmployeeDataBaseOutput::GetAllEmployees
中的new
.
class EmployeeDataBaseOutput{
private:
DataBaseConnectionFactoryInterface* connect_factory_;
DataBaseCommandFactoryInterface* command_factory_;
public:
EmployeeDataBaseOutput(DataBaseConnectionFactoryInterface* connect_factory,DataBaseCommandFactoryInterface* command_factory) :
connect_factory_(connect_factory),command_factory_(command_factory) { }
vector<Employee> GetAllEmployees() {
DataBaseConnctionInterface* connection = connect_factory_->CreatDataBaseConnection();
connection->ConnectionString("...");
DataBaseCommandInterface* command = command_factory_->CreatDataBaseCommand();
command->CommandText("...");
command->SetConnection(connection);
DataBaseDataReaderInterface* reader = command->ExecuteReader();
while(reader->Read()) {
}
}
};
但是这里我们需要注意的是,DataBaseConnectionFactoryInterface* connect_factory_; DataBaseCommandFactoryInterface* command_factory_;
是有关联的,他们两个应该是相同类型的数据库,我们不能让connection
是sql
而command
是oracle
.他们两个应该是统一的.
所以我们应该考虑.用一个同一个工厂来产生Conect
和Command
.我们现在把工厂进行一下修改.
class DataBaseFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() = 0;
virtual DataBaseCommandInterface* CreatDataBaseCommand()=0;
~DataBaseFactoryInterface() { }
};
class SqlFactory : public DataBaseFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() {
return new SqlConnection();
}
virtual DataBaseCommandInterface* CreatDataBaseCommand() {
return new SqlCommand();
}
};
class OracleFactory : public DataBaseFactoryInterface {
public:
virtual DataBaseConnctionInterface* CreatDataBaseConnection() {
return new OracleConnection();
}
virtual DataBaseCommandInterface* CreatDataBaseCommand() {
return new OracleCommand();
}
};
继续更改EmployeeDataBaseOutput
class EmployeeDataBaseOutput{
private:
DataBaseFactoryInterface* data_base_factory_;
public:
EmployeeDataBaseOutput(DataBaseFactoryInterface* data_base_factory) : data_base_factory_(data_base_factory) { }
vector<Employee> GetAllEmployees() {
DataBaseConnctionInterface* connection = data_base_factory_->CreatDataBaseConnection();
connection->ConnectionString("...");
DataBaseCommandInterface* command = data_base_factory_->CreatDataBaseCommand();
command->CommandText("...");
command->SetConnection(connection);
DataBaseDataReaderInterface* reader = command->ExecuteReader();
while(reader->Read()) {
}
}
};
类图
总结
- 如果没有应对多系列对象构建的需求变化,则没有必要使用AbstractFactory 模式,这时候使用简单工厂就可以
- "系列对象"指的是在某一特定系列下的对象之间有相互依赖,或相互作用关系.
- Abstract Factory 主要在于应对"新系列"的需求变动,难于应对新对象的需求变动.