- 前言
- Abstract Factory设计模式
- 1.模式的应对场景
- 2.案例1:数据库的connection、command依赖
- 3.产品族和产品等级
- 4.案例2
- 5.模式定义
- 6.模式结构
- 7.要点总结
在学习侯捷老师的有关设计模式的课程(李建忠老师主讲)中,老师对23种设计模式的有自己的划分,如下。所以老师讲解是按照这种顺序讲解。
对象创建:
和工厂模式不同,它解决的是单一的对象创建工作。抽象工厂模式解决的是“一系列相互依赖的对象”的创建工作。
设计模式之工厂模式(Factor Method)
2.案例1:数据库的connection、command依赖先给代码再说明:
#include#include using namespace std; //database connection class IDBConnection { public: virtual void ConnectionString() = 0; }; class SqlConnection : public IDBConnection { public: void ConnectionString(){ cout << "Sql connection" << endl; } }; class MysqlConnection : public IDBConnection { public: void ConnectionString(){ cout << "Mysql connection" << endl; } }; //database command class IDBCommand { public: virtual void CommandText() = 0; virtual void SetConnection(IDBConnection* connect) = 0; }; class SqlCommand : public IDBCommand { public: void CommandText(){ cout << "Sql command text" << endl; } void SetConnection(IDBConnection* connect){ cout << "set connection with "; connect->ConnectionString(); } }; class MysqlCommand : public IDBCommand { public: void CommandText(){ cout << "Mysql command text" << endl; } void SetConnection(IDBConnection* connect){ cout << "set connection with "; connect->ConnectionString(); } }; //抽象工厂 class IDBFactor { public: virtual IDBConnection* creatDBConnection() = 0; virtual IDBCommand* creatDBCommand() = 0; }; //sql 工厂 class SqlFactor : public IDBFactor { public: virtual IDBConnection* creatDBConnection() { return new SqlConnection; } virtual IDBCommand* creatDBCommand() { return new SqlCommand; } }; //Mysql 工厂 class MysqlFactor : public IDBFactor { public: virtual IDBConnection* creatDBConnection() { return new MysqlConnection; } virtual IDBCommand* creatDBCommand() { return new MysqlCommand; } }; class EmployeeDAO { IDBFactor* dbfactor; public: EmployeeDAO(){} EmployeeDAO(IDBFactor* _dbfactor) : dbfactor(_dbfactor){} void GetEmployees(){ //IDBConnection* connection = new SqlConnection(); IDBConnection* connection = dbfactor->creatDBConnection(); connection->ConnectionString(); //IDBCommand* command = new SqlCommand(); IDBCommand* command = dbfactor->creatDBCommand(); command->CommandText(); command->SetConnection(connection); } }; int main() { EmployeeDAO e(new MysqlFactor); e.GetEmployees(); EmployeeDAO e1(new SqlFactor); e1.GetEmployees(); system("pause"); return 0; }
EmployeeDAO类中,由于Connection和Command是相互依赖,所以我们把这两个对象的创建放在一个抽象工厂IDBFactor,然后分别有SqlFactor 和MysqlFactor 两个具体工厂,各自创建自己的Connection和Command(SqlConnection、SqlCommand和MysqlConnection、MysqlCommand)相关类。
使用工厂模式的影响:
如果用工厂模式分别生成这两个对象,那么可能会存在这样一种情况:即我们生成了一个SqlConnection,但是command却是MysqlCommand,代码如下:
#if 1 #include#include using namespace std; //database connection class IDBConnection { public: virtual void ConnectionString() = 0; }; class SqlConnection : public IDBConnection { public: void ConnectionString(){ cout << "Sql connection" << endl; } }; class MysqlConnection : public IDBConnection { public: void ConnectionString(){ cout << "Mysql connection" << endl; } }; class IDBConnectionFactor { public: virtual IDBConnection* creatorIDBConnection() = 0; }; class SqlConnectionFactor : public IDBConnectionFactor { public: virtual IDBConnection* creatorIDBConnection(){ return new SqlConnection; } }; class MySqlConnectionFactor : public IDBConnectionFactor { public: virtual IDBConnection* creatorIDBConnection(){ return new MysqlConnection; } }; //database command class IDBCommand { public: virtual void CommandText() = 0; virtual void SetConnection(IDBConnection* connect) = 0; }; class SqlCommand : public IDBCommand { public: void CommandText(){ cout << "Sql command text" << endl; } void SetConnection(IDBConnection* connect){ cout << "Sql set connection with "; connect->ConnectionString(); } }; class MysqlCommand : public IDBCommand { public: void CommandText(){ cout << "Mysql command text" << endl; } void SetConnection(IDBConnection* connect){ cout << "Mysql set connection with "; connect->ConnectionString(); } }; class IDBCommandFactor { public: virtual IDBCommand* creatorIDBCommand() = 0; }; class SqlCommandFactor : public IDBCommandFactor { public: virtual IDBCommand* creatorIDBCommand(){ return new SqlCommand; } }; class MySqlCommandFactor : public IDBCommandFactor { public: virtual IDBCommand* creatorIDBCommand(){ return new MysqlCommand; } }; class EmployeeDAO { IDBConnectionFactor* connectionfactor; IDBCommandFactor* commandfactor; public: EmployeeDAO(){} EmployeeDAO(IDBConnectionFactor* _connectionfactor, IDBCommandFactor* _commandfactor) : connectionfactor(_connectionfactor), commandfactor(_commandfactor){} void GetEmployees(){ //IDBConnection* connection = new SqlConnection(); IDBConnection* connection = connectionfactor->creatorIDBConnection(); connection->ConnectionString(); //IDBCommand* command = new SqlCommand(); IDBCommand* command = commandfactor->creatorIDBCommand(); command->CommandText(); command->SetConnection(connection); } }; int main() { EmployeeDAO e(new SqlConnectionFactor, new MySqlCommandFactor); e.GetEmployees(); system("pause"); return 0; } #endif
这里就会有两个工厂数据成员,在客户使用EmployeeDAO类时,就可能出现下图中创建对象不搭配的情况。
李建忠老师在讲解抽象工厂模式时,并没有提到关于产品族和产品等级这个概念,但是我发现网上很多关于抽象工厂的文章中都提到了这个概念,所以在这里稍微说一下我的理解。
拿案例1举例,我们可以做这样的一个划分:
如果我们增加一个产品族,程序是可以很好扩展,不会违背开闭原则;但是如果我们增加一个产品等级,你会发现就需要修改而不是扩展代码,会违背开闭原则。
这里你可能会比较难区分什么是产品族?什么是产品等级?我的理解就是:
因为抽象工厂模式解决的就是“一系列相互依赖的对象”的创建工作,所以这系列对象就是一个产品族,不是一族怎么会相互依赖呢!
下面在举一个例子,如下所示是产品族和产品等级。
图片来源:链接
假设我们的客户程序是先打开手机和路由器,再通过手机控制路由器,伪代码如下;
class Client
{
public:
void getWorking(){
generate 手机;
手机start;
generate 路由器;
路由器start;
手机控制路由器;
}
}
代码还是很简单写的,下面一步步写:
下面开始代码:
1.先来写华为手机和路由器的类+Client类并做简单测试(不用抽象工厂模式)
#include#include using namespace std; //手机基类 class IPhone { public: virtual void phoneStart() = 0; virtual string phoneName() = 0; }; class HuaweiPhone : public IPhone { public: virtual void phoneStart() { cout << "华为手机开机" << endl; } virtual string phoneName() { return string("华为"); } }; //路由器基类 class IRouter { public: virtual void routerStart() = 0; virtual void control(IPhone* _phone) = 0; }; class HuaweiRouter : public IRouter { public: virtual void routerStart() { cout << "华为路由器开机" << endl; } virtual void control(IPhone* _phone) { cout << "华为路由器被" << _phone->phoneName()<<"手机控制"<< endl; } }; //客户 class Client { public: void getWorking() { IPhone* phone = new HuaweiPhone; phone->phoneStart(); IRouter* router = new HuaweiRouter; router->routerStart(); router->control(phone); } }; int main() { Client c; c.getWorking(); system("pause"); return 0; }
2.扩展出小米手机和路由器的类+加入抽象工厂模式
#include5.模式定义 6.模式结构#include using namespace std; //手机基类 class IPhone { public: virtual void phoneStart() = 0; virtual string phoneName() = 0; }; class HuaweiPhone : public IPhone { public: virtual void phoneStart() { cout << "华为手机开机" << endl; } virtual string phoneName() { return string("华为"); } }; class XiaomiPhone : public IPhone { public: virtual void phoneStart() { cout << "小米手机开机" << endl; } virtual string phoneName() { return string("小米"); } }; //路由器基类 class IRouter { public: virtual void routerStart() = 0; virtual void control(IPhone* _phone) = 0; }; class HuaweiRouter : public IRouter { public: virtual void routerStart() { cout << "华为路由器开机" << endl; } virtual void control(IPhone* _phone) { cout << "华为路由器被" << _phone->phoneName()<<"手机控制"<< endl; } }; class XiaomiRouter : public IRouter { public: virtual void routerStart() { cout << "小米路由器开机" << endl; } virtual void control(IPhone* _phone) { cout << "小米路由器被" << _phone->phoneName() << "手机控制" << endl; } }; class IAbstractFactor { public: virtual IPhone* creatPhone() = 0; virtual IRouter* creatRouter() = 0; }; //华为工厂 class HuaweiFactor : public IAbstractFactor { public: virtual IPhone* creatPhone() { return new HuaweiPhone; } virtual IRouter* creatRouter(){ return new HuaweiRouter; } }; //小米工厂 class XiaomiFactor : public IAbstractFactor { public: virtual IPhone* creatPhone() { return new XiaomiPhone; } virtual IRouter* creatRouter(){ return new XiaomiRouter; } }; //客户 class Client { IAbstractFactor* factor; public: Client(IAbstractFactor* _factor) : factor(_factor){} void getWorking() { IPhone* phone = factor->creatPhone(); phone->phoneStart(); IRouter* router = factor->creatRouter(); router->routerStart(); router->control(phone); } }; int main() { Client c(new HuaweiFactor); c.getWorking(); Client c1(new XiaomiFactor); c1.getWorking(); system("pause"); return 0; }
一个工厂(ConcreteFactor1)生产一系列相互依赖的对象(ProductA1 ProductB1)。
- 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
- “系列对象”指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象(就像案例一中的MysqlCommand、SqlConnection)之间不能相互依赖。
- Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。(意思就是无法应对产品等级的增加)



