设计模式之抽象工厂模式(Abstract Factory)

目录

  • 前言
  • Abstract Factory设计模式
    • 1.模式的应对场景
    • 2.案例1:数据库的connection、command依赖
    • 3.产品族和产品等级
    • 4.案例2
    • 5.模式定义
    • 6.模式结构
    • 7.要点总结

前言

在学习侯捷老师的有关设计模式的课程(李建忠老师主讲)中,老师对23种设计模式的有自己的划分,如下。所以老师讲解是按照这种顺序讲解。
在这里插入图片描述
对象创建:
设计模式之抽象工厂模式(Abstract Factory)_第1张图片

Abstract Factory设计模式

1.模式的应对场景

和工厂模式不同,它解决的是单一的对象创建工作。抽象工厂模式解决的是“一系列相互依赖的对象”的创建工作。

设计模式之工厂模式(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(); }
};


/***********工厂介入 start*****************************/

//抽象工厂
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;
	}
};

/***********工厂介入 end*****************************/


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,然后分别有SqlFactorMysqlFactor 两个具体工厂,各自创建自己的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; }
};


/***connection工厂***/
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; }
};
/***connection工厂***/


//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(); }
};

/***Command工厂***/
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; }
};
/***Command工厂***/


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类时,就可能出现下图中创建对象不搭配的情况。
设计模式之抽象工厂模式(Abstract Factory)_第2张图片

3.产品族和产品等级

李建忠老师在讲解抽象工厂模式时,并没有提到关于产品族和产品等级这个概念,但是我发现网上很多关于抽象工厂的文章中都提到了这个概念,所以在这里稍微说一下我的理解。

拿案例1举例,我们可以做这样的一个划分:
设计模式之抽象工厂模式(Abstract Factory)_第3张图片
如果我们增加一个产品族,程序是可以很好扩展,不会违背开闭原则;但是如果我们增加一个产品等级,你会发现就需要修改而不是扩展代码,会违背开闭原则。

这里你可能会比较难区分什么是产品族?什么是产品等级?我的理解就是:
因为抽象工厂模式解决的就是“一系列相互依赖的对象”的创建工作,所以这系列对象就是一个产品族,不是一族怎么会相互依赖呢!

4.案例2

下面在举一个例子,如下所示是产品族和产品等级。设计模式之抽象工厂模式(Abstract Factory)_第4张图片
图片来源:链接

假设我们的客户程序是先打开手机和路由器,再通过手机控制路由器,伪代码如下;

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;
}

设计模式之抽象工厂模式(Abstract Factory)_第5张图片

2.扩展出小米手机和路由器的类+加入抽象工厂模式

#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 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;
	}
};


/******抽象工厂介入 start******/
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; }
};

/******抽象工厂介入 end******/



//客户
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;
}

5.模式定义

设计模式之抽象工厂模式(Abstract Factory)_第6张图片

6.模式结构

设计模式之抽象工厂模式(Abstract Factory)_第7张图片
一个工厂(ConcreteFactor1)生产一系列相互依赖的对象(ProductA1 ProductB1)。

7.要点总结

  1. 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
  2. “系列对象”指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象(就像案例一中的MysqlCommand、SqlConnection)之间不能相互依赖。
  3. Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。(意思就是无法应对产品等级的增加

你可能感兴趣的:(设计模式,设计模式,抽象工厂模式,c++,abstractfactory)