工厂模式

工厂模式:主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可分为:

  1. 简单工厂模式(Simple Factory);
  2. 工厂方法模式(Factory Method);
  3. 抽象工厂模式(Abstract Factory)。

这三种模式从上到下逐步抽象,并更具有一般性。

为了更加能体会工厂模式的意义,先举一个简单例子。通常我们在实现一个简单计算器Demo时。

可能编写如下代码:

/* 计算器Demo*/
#include <iostream>

using namespace std;

double Calcium(double numA, double numB, char op){
	double result = 0;

	switch (op){
	case'+':
		result =  numA + numB;
		break;
	case'-':
		result = numA - numB;
		break;
	case'*':
		result = numA*numB;
		break;
	case'/':
		if (numB == 0){
			cout << "不能除以 0 !!!" << endl;
			break;
		}
		result = numA / numB;
		break;
	default: break;
	}

	return result;
}

int main(){
	cout << Calcium(1, 2, '+') << endl;

	return 0;
}

对于我们常用的"+,-,*,/"运算是没有问题的,但是上面实现仅仅能满足当前的需求,代码强耦合,如果调用Calcium出错则直接导致程序崩溃,比如:我们需要开方操作时,我们得添加该操作到方法中,并重新编译整个程序,而在修改时如果将其他分支修改了,也会造成程序错误。所以程序的维护性、扩展性、复用性很差。

 

简单工厂模式:

简单工厂模式又称静态工厂方法模式

它主要是定义了一个用于创建对象的接口

计算器简单工厂模式结构图

 

/* 简单工厂模式 */

#include <iostream>
#include <unordered_map>

using namespace std;

unordered_map<string, int>mm { { "+", 1 }, { "-", 2 }, { "*", 3}, { "/", 4 } };

class Operation{
public:
	void SetNumberA(double numA){
		_numA = numA;
	}

	void SetNumberB(double numB){
		_numB = numB;
	}

	double GetNumberA(){
		return _numA;
	}

	double GetNumberB(){
		return _numB;
	}

	virtual double GetResult(){
		double result = 0;
		return result;
	}

private:
	double _numA;
	double _numB;
};

class Add :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() + GetNumberB();
		return result;
	}
};

class Sub :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() - GetNumberB();
		return result;
	}
};

class Mul :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() * GetNumberB();
		return result;
	}
};

class Div :public Operation{
public:
	double GetResult(){
		double result = 0;
		if (GetNumberB() == 0)
			throw "不能除以 0 !!!";
		result = GetNumberA() / GetNumberB();
		return result;
	}
};

class OperationFactory{
public:
	static Operation* CreateOperate(string operate){
		Operation* op = nullptr;
		int i = mm[operate];
		switch (i)
		{
		case 1:
			op = new Add();
			break;
		case 2:
			op = new Sub();
			break;
		case 3:
			op = new Mul();
			break;
		case 4:
			op = new Div();
			break;
		default:
			break;
		}

		return op;
	}

};

int main()
{
	Operation* oper;
	oper = OperationFactory::CreateOperate("/");
	oper->SetNumberA(12);
	oper->SetNumberB(0);
	try{
		cout << oper->GetResult() << endl;
	}
	catch (const char* msg){
		cout << msg << endl;
	}

	return 0;
}

在简单工厂模式下,如果我们要对程序操作进行扩展,可以直接写一个类继承Operation类,然后独立编写该类,而不会影响到其他模块。在之后运行中如果出现问题,也能很快排错,仅仅修改错误模块的代码。通过继承Operation类的成员变量、成员方法提高了代码复用性。

此外工厂类中包含了必要的逻辑判断,根据客户端的具体调用动态实例化相关类。对于客户端去除了与具体产品的依赖。

通过比较,简单工厂模式的优点不言而喻。

 

工厂方法模式:

工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

通过之前简单工厂我们实现了业务逻辑与显示逻辑的分离,工厂类通过判断客户需求而实例化不同的类。但也导致工厂类与其分支的强耦合,再者我们如果要添加其他操作时,就需要修改工厂类的switch-case语句,而这就违反了开放-封闭原则。可以有依赖倒转原则抽象化工厂类,之后的添加功能只需增加相应工厂类和运算类,修改也只对自己类模块修改。

计算器工厂方法结构图

 

/* 工厂方法模式 */
#include <iostream>

using namespace std;

class Operation{
public:
	void SetNumberA(double numA){
		_numA = numA;
	}

	void SetNumberB(double numB){
		_numB = numB;
	}

	double GetNumberA(){
		return _numA;
	}

	double GetNumberB(){
		return _numB;
	}

	virtual double GetResult(){
		double result = 0;
		return result;
	}

private:
	double _numA;
	double _numB;
};

class Add :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() + GetNumberB();
		return result;
	}
};

class Sub :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() - GetNumberB();
		return result;
	}
};

class Mul :public Operation{
public:
	double GetResult(){
		double result = 0;
		result = GetNumberA() * GetNumberB();
		return result;
	}
};

class Div :public Operation{
public:
	double GetResult(){
		double result = 0;
		if (GetNumberB() == 0)
			throw "不能除以 0 !!!";
		result = GetNumberA() / GetNumberB();
		return result;
	}
};

class IFactory{
public:
	virtual Operation* CreateFactory() = 0;
};

class AddFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Add();
	}
};

class SubFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Sub();
	}
};

class MulFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Mul();
	}
};

class DivFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Div();
	}
};


int main()
{
	IFactory* operFactory = new AddFactory();
	Operation* oper = operFactory->CreateFactory();
	oper->SetNumberA(1);
	oper->SetNumberB(2);
	try{
		cout << oper->GetResult() << endl;
	}
	catch (const char* msg){
		cout << msg << endl;
	}

	return 0;
}

通过实现工厂方法模式,我们将判断逻辑交给了客户,客户完全根据自己需求去实例化。

使用工厂方法模式情形:
    1)  当客户程序不需要知道要使用对象的创建过程。
    2)  客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

 

抽象工厂模式:

抽象工厂模式:提供一个创建一系列相关或依赖对象的接口,而无需指定它们具体的类。

接着之前的例子,如果我们再需要添加某种功能?比如:打印正进行的是什么运算。(很鸡肋,但想不到了orz.)。那么我们该怎么办?

有了之前的基础,我们可以再提供一个抽象类接口:Print 。通过此接口来实现具体的不同运算类。再将创建子类实例的抽象方法写到抽象工厂中,之后实现的就是具体的运算工厂。

计算器抽象工厂结构

 

/* Print接口及其分类 */
class Print{
public:
	virtual void PrintStatement() = 0;
};

class AddPrint: public Print{
public:
	void PrintStatement(){
		cout << "这是加法 !!!" << endl;
	}
};


class SubPrint : public Print{
public:
	void PrintStatement(){
		cout << "这是减法 !!!" << endl;
	}
};


class MulPrint : public Print{
public:
	void PrintStatement(){
		cout << "这是乘法 !!!" << endl;
	}
};


class DivPrint : public Print{
public:
	void PrintStatement(){
		cout << "这是除法 !!!" << endl;
	}
};

 

/* 将该功能添加到我们工厂中 */
class IFactory{
public:
	virtual Operation* CreateFactory() = 0;
	virtual Print* CreatePrintFactory() = 0;
};

class AddFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Add();
	}

	Print* CreatePrintFactory(){
		return new AddPrint();
	}
};

class SubFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Sub();
	}

	Print* CreatePrintFactory(){
		return new SubPrint();
	}
};

class MulFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Mul();
	}

	Print* CreatePrintFactory(){
		return new MulPrint();
	}
};

class DivFactory :public IFactory{
public:
	Operation* CreateFactory(){
		return new Div();
	}

	Print* CreatePrintFactory(){
		return new DivPrint();
	}
};
/* 客端调用 */
int main()
{
	IFactory* operFactory = new AddFactory();
	Operation* oper = operFactory->CreateFactory();
	oper->SetNumberA(1);
	oper->SetNumberB(2);
	try{
		cout << oper->GetResult() << endl;
	}
	catch (const char* msg){
		cout << msg << endl;
	}

	
	Print* prt = operFactory->CreatePrintFactory();
	prt->PrintStatement();
	return 0;
}

IFactory是一个抽象工厂接口,它包含所有产品创建的抽象方法。

AddFactory、SubFactory...就是具体的工厂,通常就是在运行时刻创建具体工厂的实例,通过具体工厂来创建特定的产品对象,也就是创建不同产品对象,客户端应使用不同具体工厂。

使用条件:

  1. 系统中有多个产品族,而系统一次只可能消费其中一族产品。
  2. 同属于同一个产品族的产品一起使用。

 

本篇参照《大话设计模式》、《深入浅出设计模式》、《设计模式:可复用面向对象软件的基础》相关章节内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值