抽象工厂模式,又称Abstract Factory模式,相对于工厂模式,抽象工厂模式是将几个具有关联性的对象合并在一个工厂中创建。
定义
提供一个接口,让该接口负责创建一系列“相关或者相互依 赖的对象”,无需指定它们具体的类。 — 《设计模式》 GoF
动机
在工厂模式中,一个工厂接口产生一个抽象的工厂对象,一组具体的工厂产生每一个具体的对象,重载工厂方法,但是在实际使用中,我们有时候需要产生多个抽象的对象,并且每一个抽象的对象都对应各种不同的具体对象,这时我们可以使用抽象工厂将这些抽象的对象放在一个工厂中产生,下面的工厂继承抽象工厂,重载工厂方法返回一组具体的对象。
抽象工厂方法可以产生一个产品族中的所有对象,比工厂方法效率更高,更简单。
Abstract Factory模式主要在于应对“新系列”的需求变动,其缺点在于难以应对“新对象”的需求变动。
模式分析
- AbstractFactory:抽象工厂,返回多个产品
- ConcreteFactory:具体工厂,返回多个具体的产品
- AbstractProduct : 抽象产品,多个抽象产品组成产品族
- Product: 具体产品
代码分析
本文举一个数据库操作的例子,数据库操作需要分为先获取指令,再连接两个步骤,而数据库又有不同的类型,如Sql和Oracle,可以把获取指令和连接看成两个抽象的产品,每个数据库对应这两个步骤有不同的操作,看着具体的产品,使用抽象工厂方法设计。
这种连个维度的变化联想到了桥模式,但是这里不适合使用桥模式,原因在于获取指令和连接两个步骤对于不同的数据库来说不是随机组合的,而是绑定的,即如果获取指令使用的是Sql数据库,那么连接也必须是Sql数据库。
抽象产品
抽象产品是指获取指令和连接两个类,都是接口
class IDBCommand
{
public:
IDBCommand();
~IDBCommand();
virtual void getCommond() = 0;
};
class IDBConnection
{
public:
IDBConnection();
~IDBConnection();
virtual void getConnection() = 0;
};
具体的产品
具体的产品分别继承自抽象产品,每个操作下面分别对应两个数据库,因此具体的产品有4种
class OracleCommand : public IDBCommand
{
public:
OracleCommand();
virtual ~OracleCommand();
virtual void getCommond();
};
void OracleCommand::getCommond()
{
printf("get oracle commond... \n");
}
class OracleConnection : public IDBConnection
{
public:
OracleConnection();
virtual ~OracleConnection();
virtual void getConnection();
};
void OracleConnection::getConnection()
{
printf("get oracle Connection... \n");
}
class SqlCommand : public IDBCommand
{
public:
SqlCommand();
~SqlCommand();
virtual void getCommond();
};
void SqlCommand::getCommond()
{
printf("get Sql commond... \n");
}
class SqlConnection : public IDBConnection
{
public:
SqlConnection();
~SqlConnection();
virtual void getConnection();
};
void SqlConnection::getConnection()
{
printf("get Sql Connection... \n");
}
抽象工厂
抽象工厂负责产生两个产品,即获取指令和连接
具体产生什么产品,放在具体的工厂中
class IDBFactory
{
public:
IDBFactory();
~IDBFactory();
virtual IDBCommand *getIDBCommand() = 0;
virtual IDBConnection *getIDBConnection() = 0;
};
具体的工厂
负责产生Sql对应的产品和Oracle对应的产品
class SqlDBFactory : public IDBFactory
{
public:
SqlDBFactory();
~SqlDBFactory();
virtual IDBCommand *getIDBCommand();
virtual IDBConnection *getIDBConnection();
};
IDBCommand * SqlDBFactory::getIDBCommand()
{
return new SqlCommand;
}
IDBConnection * SqlDBFactory::getIDBConnection()
{
return new SqlConnection;
}
class OracleDBFactory : public IDBFactory
{
public:
OracleDBFactory();
~OracleDBFactory();
virtual IDBCommand *getIDBCommand();
virtual IDBConnection *getIDBConnection();
};
IDBCommand * OracleDBFactory::getIDBCommand()
{
return new OracleCommand;
}
IDBConnection * OracleDBFactory::getIDBConnection()
{
return new OracleConnection;
}
MainForm类
这个类模拟使用数据库的类,这个类首先传入具体的工厂产生两个具体的产品,然后分别调用里面的函数。
MainForm作为上层应用应该是稳定的。
class MainForm
{
public:
MainForm(IDBFactory *dbfactory);
~MainForm();
IDBFactory *dbfactory;
void getdata();
};
MainForm::MainForm(IDBFactory *dbfactory)
{
this->dbfactory = dbfactory;
}
MainForm::~MainForm()
{
}
void MainForm::getdata()
{
IDBCommand *dbcommand = dbfactory->getIDBCommand();
IDBConnection *dbconnection = dbfactory->getIDBConnection();
dbcommand->getCommond();
dbconnection->getConnection();
}
main函数测试
先使用多态的方法创建一个工厂,再把这个工厂传入MainForm中。
int main()
{
IDBFactory *dbfactory = new SqlDBFactory;
MainForm *mainform = new MainForm(dbfactory);
mainform->getdata();
}
- 测试结果
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!