构造型设计模式--工厂模式


工厂模式分三种类型:简单工厂模式、工厂方法模式、抽象工厂模式。

1、开发需求

假设:实现一个项目,需要有多种通信方式,譬如UDP、组播、TCP、CPCI等,为了工作方便,几部分通信方式分别找了几个熟练的程序员进行开发。假设我提供他们的接口为:

//ICommunicate.h

#ifndef ICOMMUNICATE_H
#define ICOMMUNICATE_H

class ICommunicate
{
public:
	virtual void start() = 0;
};

#endif

其中,UDP实现为:

//ComunicateUDP.h

#pragma once
#include "icommunicate.h"
#include <iostream>
using namespace std;
class ComunicateUDP :
	public ICommunicate
{
public:
	ComunicateUDP(void);
	~ComunicateUDP(void);

	virtual void start();
};
//ComunicateUDP.cpp

#include "StdAfx.h"
#include "ComunicateUDP.h"


ComunicateUDP::ComunicateUDP(void)
{

}


ComunicateUDP::~ComunicateUDP(void)
{
}

void ComunicateUDP::start(){

	cout<<"udp start!"<<endl;

}

TCP实现为:

//CommunicateTCP.h

#pragma once
#include "icommunicate.h"
#include <iostream>
using namespace std;

class CommunicateTCP :
	public ICommunicate
{
public:
	CommunicateTCP(void);
	~CommunicateTCP(void);

	virtual void start();
};
//CommunicateTCP.cpp

#include "StdAfx.h"
#include "CommunicateTCP.h"


CommunicateTCP::CommunicateTCP(void)
{
}


CommunicateTCP::~CommunicateTCP(void)
{
}

void CommunicateTCP::start(){

	cout<<"tcp start!"<<endl;

}

而我们如果需要使用他们的模块,可以在主程序中使用:

// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "ICommunicate.h"

#include "ComunicateUDP.h"
#include "CommunicateTCP.h"
 
int _tmain(int argc, _TCHAR* argv[])
{
     ICommunicate * pCom1 = new ComunicateUDP(); 
     ICommunicate * pCom2 = new CommunicateTCP();
 
     pCom1->start();
     pCom2->start();
 
     delete pCom1;
     delete pCom2;
 
     pCom1 = NULL;
     pCom2 = NULL; 
     return 0;
}

2、进一步考虑,使用简单工厂模式

2.1简单工厂模式的实现

上面的解决方案虽然可以实现功能,但是在使用不同的通信方式时,还存在一个问题:假如,需要使用这几种的通信方式时,还需要在主程序中调用对应的头文件、以及new一个他的实例,这样的话,会大大增加程序的耦合度。
事实上,开发者并不需要知道具体的类的名字、具体在哪个头文件中,而只需要一个通用的接口来实现不同的实例。

// CommunicateFactory.h

#pragma once
#include "ICommunicate.h"
#include "ComunicateUDP.h"
#include "CommunicateTCP.h"
class CommunicateFactory
{
public:
	CommunicateFactory(void);
	~CommunicateFactory(void);

	ICommunicate *createCommunicate(string);
};
// CommunicateFactory.cpp

#include "StdAfx.h"
#include "CommunicateFactory.h"


CommunicateFactory::CommunicateFactory(void)
{
}


CommunicateFactory::~CommunicateFactory(void)
{
}
ICommunicate *CommunicateFactory::createCommunicate(string type)
{
	ICommunicate * pCom = NULL; 
	if(type.compare("UDP") == 0){
		pCom = new ComunicateUDP();
	}
	else if(type.compare("TCP") == 0){
		pCom = new CommunicateTCP();
	}
	else{
		// ... ...
	}
	return pCom;

}

通过一个工厂类,实现了对通信不同实例的封装,而主函数只需要一个接口类、一个工厂类就可以实现其需要的功能。

// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#include "ICommunicate.h"
#include "CommunicateFactory.h"

int _tmain(int argc, _TCHAR* argv[])
{
	ICommunicate * pCom;
	CommunicateFactory m_CommunicateFactory;
	pCom = m_CommunicateFactory.createCommunicate("UDP");

	pCom->start();

	delete pCom;
	pCom = NULL;

	return 0;
}

由上,即可以实现了简单工厂模式,简单工厂不是GoF的23种标准设计模式,其实就是一个专门生产不同产品的类,这个类通过传入的参数进行区分要生产的东西!

2.2简单工厂模式的问题

当我们需要增加新的通信方式的时候,需要做的工作有:继承ICommunicate.h接口,然后写一个新的.cpp,并且修改简单工厂类,为其增加一个新的条件分支。后续维护过程中,需要不断完善修改简单工厂模式类。

3、工厂方法模式

工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。工厂方法模式主要是将每一个具体产品写一个工厂,取代以前的一个工厂类,主要缺点就是增加了代码量。
其改写方法主要是:
首先,增加一个工厂方法接口:

// IFacory.h
#ifndef IFacory_H
#define IFacory_H

#include "ICommunicate.h"

class IFacory
{
public:
	virtual ICommunicate* createCommunicate() = 0;
};

#endif

然后分别实现各个产品的工厂类:

//FacoryUDP.h
#pragma once
#include "ifacory.h"

#include "ComunicateUDP.h"
class FacoryUDP :
	public IFacory
{
public:
	FacoryUDP(void);
	~FacoryUDP(void);

	virtual ICommunicate* createCommunicate();
};


//FacoryUDP.cpp
#include "StdAfx.h"
#include "FacoryUDP.h"


FacoryUDP::FacoryUDP(void)
{
}


FacoryUDP::~FacoryUDP(void)
{
}

ICommunicate* FacoryUDP::createCommunicate()
{
	return new ComunicateUDP();
}

//FacoryTCP.h
#pragma once
#include "ifacory.h"

#include "CommunicateTCP.h"
class FacoryTCP :
	public IFacory
{
public:
	FacoryTCP(void);
	~FacoryTCP(void);

	virtual ICommunicate* createCommunicate();
};


//FacoryTCP.cpp
#include "StdAfx.h"
#include "FacoryTCP.h"


FacoryTCP::FacoryTCP(void)
{
}


FacoryTCP::~FacoryTCP(void)
{
}

ICommunicate* FacoryTCP::createCommunicate()
{
	return new CommunicateTCP();
}


最后在使用上进行修改:

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "ICommunicate.h"
//#include "CommunicateFactory.h"

#include "IFacory.h"
#include "FacoryUDP.h"
#include "FacoryTCP.h"

int _tmain(int argc, _TCHAR* argv[])
{
	ICommunicate * pCom;
	//CommunicateFactory m_CommunicateFactory;
	//pCom = m_CommunicateFactory.createCommunicate("UDP");

	//pCom->start();

	IFacory *iFy;
	iFy = new FacoryUDP();
	pCom = iFy->createCommunicate();
	pCom->start();

	delete pCom;
	pCom = NULL;

	return 0;
}


可以看到,如果需要增加新的产品,不需要在已有的基础上进行修改,只需要进行增加对应的工厂类即可,其在设计上完全符合“开放封闭”原则,但是也带来较大的代码量,增加了类的个数,增加了复杂程度

4、抽象工厂模式

抽象工厂模式可以较好的实现“开放封闭”原则,有能够有效控制住代码的复杂度,不至于像工厂方法模式那样,每增加一个产品都要增加一个工厂。其表现更像是工厂方法+简单工厂模式的结合!
对于上面的项目,其改造过程为:
首先,定义抽象工厂接口,用来生产不同产品,生产不同产品,既可以通过一个接口传参数来区分,也可以通过不同的接口函数区分。

// IFactoryCommunicate.h
#ifndef IFactoryCommunicate_H
#define IFactoryCommunicate_H

#include "ICommunicate.h"
#include <iostream>
using namespace std;
class IFactoryCommunicate
{
public:
	virtual ICommunicate* createCommunicate(string) = 0;
};

#endif

将通信方式定义成网络通信和串口通信两种大的抽象类,TCP、UDP都定义在网络通信工厂中,下面实现以下网络通信工厂函数:

//NetCommunicateFactory.h
#pragma once
#include "IFactoryCommuncate.h"
#include "ComunicateUDP.h"
#include "CommunicateTCP.h"
class NetCommunicateFactory :
	public IFactoryCommunicate
{
public:
	NetCommunicateFactory(void);
	~NetCommunicateFactory(void);

	virtual ICommunicate* createCommunicate(string);
};


//NetCommunicateFactory.cpp
#include "StdAfx.h"
#include "NetCommunicateFactory.h"


NetCommunicateFactory::NetCommunicateFactory(void)
{
}


NetCommunicateFactory::~NetCommunicateFactory(void)
{
}

ICommunicate *NetCommunicateFactory::createCommunicate(string type)
{
	ICommunicate * pCom = NULL; 
	if(type.compare("UDP") == 0){
		pCom = new ComunicateUDP();
	}
	else if(type.compare("TCP") == 0){
		pCom = new CommunicateTCP();
	}
	else{
		// ... ...
	}
	return pCom;

}

而使用的方式改为:

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "ICommunicate.h"

#include "IFactoryCommuncate.h"
#include "NetCommunicateFactory.h"

int _tmain(int argc, _TCHAR* argv[])
{
	ICommunicate * pCom;
	IFactoryCommunicate *iFy;
	iFy = new NetCommunicateFactory();
	pCom = iFy->createCommunicate("UDP");
	pCom->start();

	delete pCom;
	pCom = NULL;

	return 0;
}

由此可以看到,当我们需要增加串口通信相关产品时,实现过程不需要更改网络通信工厂;而如果增加了网络通信产品,又不需要更改串口通信工厂,一定程度上满足了“开放封闭”原则。另外,也不需要每增加一个新的产品都增加对应的工厂,从一定程度上降低了代码的复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值