动机
??在软件设计中经常面对一系列相互依赖的对象 的创建工作,由于需求变化,经常面对更多对象的创建工作。
1. 引入问题
代码如下:
class EmployeeDB
{
public:
vector<EmployeeInfo> GetEmployee()
{
SqlConnect *connection = new SqlConnection();
connection->ConnectNet("ip:192.168.0.1");
SqlCommand *command = new SqlCommand();
command->Command("SELECT * FROM TENNER");
command->SetConnection(connection);
}
};
??先不考虑抽象工厂 的问题,为了文章具有通读性,先对其解决第一个问题:
- 上面函数中是写了
SqlServer 的数据库操作过程,如果后面要兼容MySQL 或者Oracle 呢?
2. 第一部优化
?兼容各种数据库
class DBConnection
{
public:
virtual DBConnection()=0;
};
class DBCommand
{
public:
virtual DBCommand()=0;
};
下面是一种数据库,另外种类的类似,就不列出来了.
class SqlDBConnection : public DBConnection
{
public:
virtual DBConnection(){}
};
class SqlDBCommand : public DBCommand
{
public:
virtual DBCommnd(){}
};
这时上面的函数就可以这样使用:
vector<EmployeeInfo> GetEmployee()
{
DBConnect *connection = new SqlConnection();
connection->ConnectNet("ip:192.168.0.1");
DBCommand *command = new SqlCommand();
command->Command("SELECT * FROM TENNER");
command->SetConnection(connection);
}
??这样我们发现所作的优化好像并没有什么,还存在问题,创建了具体的对象 ,严重耦合.
3. 使用工厂优化
首先创建连个工厂的基类,声明构建对象的纯虚函数:
class DBConnectFactory
{
public:
virtual DBConnection *DBConnectObjCreate() = 0;
};
class DBCommandFactory
{
public:
virtual DBCommand *DBCommandObjFactory() = 0;
};
针对一种数据库,构建自己的工厂
class SqlConnectFactory : public DBConnectFactory
{
public:
virtual DBConnection *DBConnectObjCreate()
{
return new SqlDBConnection();
}
};
class SqlCommandFactory : public DBCommandFactory
{
public:
virtual DBCommand *DBCommandObjCreate()
{
return new SqlDBCommand();
}
};
此时,我们最开始的函数就可以这样写
class EmployeeDB
{
public:
DBConnectFactory *dbConnectFact;
DBCommandFactory *dbCmdFact;
public:
vector<EmployeeInfo> GetEmployee()
{
DBConnect *connection = new SqlConnection();
修改 = dbConnectFact->DBConnectObjCreate();
connection->ConnectNet("ip:192.168.0.1");
DBCommand *command = new SqlCommand();
修改 = dbCmdFact->DBCommandObjCreate();
command->Command("SELECT * FROM TENNER");
command->SetConnection(connection);
}
}
还存在问题吗?答案为是。 为什么,因为有两个工厂,如果传进来的两个工厂的子类对象不是同一个数据库类型,就无法兼容。 比如传进来的是Oracle的Connect工厂,但却是MySql的Command工厂,问题是显而易见的。
4. 继续优化
??从工厂入手,也很简单,把工厂合为一个,只是合并。
class DBOptFactory
{
public:
virtual DBConnection *DBConnectObjCreate() = 0;
virtual DBCommand *DBCommandObjFactory() = 0;
};
这里实现具体工厂也需要合并:
class SqlConnectFactory : public DBConnectFactory
{
public:
virtual DBConnection *DBConnectObjCreate()
{
return new SqlDBConnection();
}
virtual DBCommand *DBCommandObjCreate()
{
return new SqlDBCommand();
}
};
如此以来,最终的代码如下:
```cpp
class EmployeeDB
{
public:
DBOptFactory *dbOptFact;
public:
vector<EmployeeInfo> GetEmployee()
{
DBConnect *connection = new SqlConnection();
修改 = dbOptFact->DBConnectObjCreate();
connection->ConnectNet("ip:192.168.0.1");
DBCommand *command = new SqlCommand();
修改 = dbOptFact->DBCommandObjCreate();
command->Command("SELECT * FROM TENNER");
command->SetConnection(connection);
}
}
?这是什么,这相当于嵌套了两层的多态。 来到这里,就需要解释一下,抽象工厂中的抽象 是什么含义: ??多态就是要实现抽象,抽象工厂就是一种不止生产一种具体类型对象的工厂,各种对象都可以生产。所以说名为组合工厂更合适.
|