设计模式——简单的工厂模式

1. 简介

  简单工厂模式又称静态工厂方法模式,属于创建型模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单的工厂模式是工厂模式中最简单实用的模式,但是它不属于23中GOF设计模式。简单的工厂模式其实就是工厂方法模式的一种特例,两者归为一类。
  在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单的工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
  我们先来看看它的组成:
  • 工厂角色:这是本模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,进而创建所需的产品对象。
  • 抽象产品角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例的公共接口。
  • 具体产品角色:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
  下面我们用类图(UML)来表示三者的关系:

2. 简单工厂模式案例分析

  现在我们来考虑一个简单的软件应用场景:比方说现在我们正在开发某个企业级加密系统,该系统有个不可或缺的功能——文档加密。在国内我们比较常见的加密算法有:IDEA 算法、RSA算法、AES算法等。考虑到实际的应用,我们的加密功能需要支持现阶段主流的加密算法。当然,我们还得考虑到未来(可能出现的更为出色的加密算法)。为此,我们还需要考虑到扩展性。
  此时,我们就可以考虑用简单的工厂模式来实现该功能了。整个功能的实现上的思路如下:我们提供一个工厂类,该工厂类职能便是通过某个参数,生产出对应的算法类——这就是工厂角色;我们还提供一个通用的算法抽象基类,该基类抽象出加密的接口——这就是抽象产品角色;最后,我们还在基类的基础上派生出各种加密算法——这就是具体的产品角色。
  下面就是具体的C++代码:
   抽象产品角色:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticProduct.h
*Author:  Huangjh
*Version:  
*Date:  2017-10-11
*Description:  用于描述加密算法的抽象基类,该类包含一个用于加密算法的纯虚函数
*Others:  
*Function List:  
*History: 
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/

#ifndef _ARITHMETIC_PRODUCT_H
#define _ARITHMETIC_PRODUCT_H

#include <string>

class CArithmeticProduct
{
public:
	CArithmeticProduct() { }
	~CArithmeticProduct() { }

	virtual void encryption(std::string strFileName) = 0;
};

#endif	//#ifndef _ARITHMETIC_PRODUCT_H
   具体产品角色——RSA:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticRSA.h
*Author:  Huangjh
*Version:
*Date:  2017-10-11
*Description:  具体的产品类——RSA加密算法
*Others:
*Function List:
*History:
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/
#ifndef _ARITHMETIC_RSA_H
#define _ARITHMETIC_RSA_H

#include <iostream>
#include <string>
#include "ArithmeticProduct.h"

class CArithmeticRSA : public CArithmeticProduct
{
public:
	CArithmeticRSA() { }
	~CArithmeticRSA() { }

	void encryption(std::string strFileName)
	{
		std::cout << "文件:" << strFileName << "进行RSA加密" << std::endl;
	}
};

#endif	//#ifndef _ARITHMETIC_RSA_H
   具体产品角色——IDEA:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticIDEA.h
*Author:  Huangjh
*Version:
*Date:  2017-10-11
*Description:  具体的产品类——IDEA加密算法
*Others:
*Function List:
*History:
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/
#ifndef _ARITHMETIC_IDEA_H
#define _ARITHMETIC_IDEA_H

#include <iostream>
#include <string>
#include "ArithmeticProduct.h"

class CArithmeticIDEA : public CArithmeticProduct
{
public:
	CArithmeticIDEA() { }
	~CArithmeticIDEA() { }

	void encryption(std::string strFileName)
	{
		std::cout << "文件:" << strFileName << "进行IDEA加密" << std::endl;
	}
};

#endif	//#ifndef _ARITHMETIC_IDEA_H
   具体产品角色——AES:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticAES.h
*Author:  Huangjh
*Version:
*Date:  2017-10-11
*Description:  具体的产品类——AES加密算法
*Others:
*Function List:
*History:
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/
#ifndef _ARITHMETIC_AES_H
#define _ARITHMETIC_AES_H

#include <iostream>
#include <string>
#include "ArithmeticProduct.h"

class CArithmeticAES : public CArithmeticProduct
{
public:
	CArithmeticAES() { }
	~CArithmeticAES() { }

	void encryption(std::string strFileName)
	{
		std::cout << "文件:" << strFileName << "进行AES加密" << std::endl;
	}
};

#endif	//#ifndef _ARITHMETIC_AES_H
   工厂角色:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticFactory.h
*Author:  Huangjh
*Version:
*Date:  2017-10-11
*Description:  工厂类——加密算法的工厂类
*Others:
*Function List:
*History:
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/
#ifndef _ARITHMETIC_FACTORY_H
#define _ARITHMETIC_FACTORY_H

#include <new>
#include "ArithmeticRSA.h"
#include "ArithmeticIDEA.h"
#include "ArithmeticAES.h"

class CArithmeticFactory
{
public:
	CArithmeticFactory() { }
	~CArithmeticFactory() { }

	//这就是用于生产具体加密算法的工厂类,只需要传入算法名称即可,
	//如后续需要添加算法,只需要编写具体的算法类和修改该方法即可
	static CArithmeticProduct *createArithmetic(std::string strArithmetic)
	{
		try
		{
			CArithmeticProduct *pArithmetic = NULL;
			if (strArithmetic == "RSA")
				pArithmetic = new CArithmeticRSA();
			else if (strArithmetic == "IDEA")
				pArithmetic = new CArithmeticIDEA();
			else if (strArithmetic == "AES")
				pArithmetic = new CArithmeticAES();
			else
				pArithmetic = NULL;

			return pArithmetic;
		}
		catch (std::bad_alloc &ex)
		{
			std::cout << "throw exception:" << ex.what() << std::endl;
			abort();
		}

	}
};

#endif	//#ifndef _ARITHMETIC_FACTORY_H
   测试程序:
/*********************************************************************************
*Copyright(C),Your Company
*FileName:  ArithmeticMain.cpp
*Author:  Huangjh
*Version:
*Date:  2017-10-11
*Description:  简单工厂模式的测试程序
*Others:
*Function List:
*History:
1.Date:
Author:
Modification:
2.…………
**********************************************************************************/
#include "ArithmeticFactory.h"

int main(void)
{
	CArithmeticProduct *pEncryptionArithmetic = CArithmeticFactory::createArithmetic("AES");
	pEncryptionArithmetic->encryption("huangjh.txt");

	delete pEncryptionArithmetic;

	return 0;
}
  运行结果如下:
文件:huangjh.txt进行AES加密
  对应简单的UML图如下:

3.简单工厂模式的优缺点

3.1 简单工厂模式的优点

  • 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。明确了各自的职责和权利,有利于整个软件体系结构的优化。

3.2 简单工厂模式的缺点

  • 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则需要改变工厂类了。
  • 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求。这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。

4. 简单工厂模式的适用场景

  当我们遇到以下情况时可以使用简单的工厂模式:
  • 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
  • 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值