C++设计模式2(工厂模式)

一、简单工厂

1. 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。

/********* Base.h *********/
#ifndef __BASE_H
#define __BASE_H

#include <string>
#include <assert.h>

using namespace std;

class CarBase
{
public:
	virtual ~CarBase(){}
	//虚函数,多态
	virtual void PrintName()
	{
		printf("汽车生产厂商:%s\n",m_strName.c_str());
	}
protected:
	//default构造函数为protected访问级别
	//意味着CarBase不能被实例化,必须被继承
	CarBase() {}

	CarBase(const std::string& name) : m_strName(name)
	{
	}

	std::string m_strName;//汽车生产厂商名称
};

class GMCar : public CarBase
{
public:
	GMCar() : CarBase("通用汽车公司")
	{}

	void PrintName()
	{
		printf("GMCar Test\n");
		CarBase::PrintName();
	}
};

class FordCar : public CarBase
{
public:
	FordCar() : CarBase("福特汽车公司")
	{
	}
	void PrintName()
	{
		printf("FordCar Test\n");
		CarBase::PrintName();
	}
};

class ToyotaCar : public CarBase
{
public:
	ToyotaCar() : CarBase("丰田汽车公司")
	{
	}
	void PrintName()
	{
		printf("ToyotaCar Test\n");
		CarBase::PrintName();
	}
};

class CarFactory
{
public:
	static CarBase* Create(const std::string& name)
	{
		CarBase * car = NULL;

		if ("GM" == name)
		{
			car = new GMCar();
		}
		else if ("Ford" == name)
		{
			car = new FordCar();
		}
		else if ("Toyota" == name)
		{
			car = new ToyotaCar();
		}
		else
		{
			assert(false);			// 弹出错误对话框
		}

		return car;
	}
};

#endif

  main函数

#include "Base.h"

void SimpleFactorTest()
{
	CarBase* car = CarFactory::Create("GM");
	car->PrintName();
	delete car;

	car = CarFactory::Create("Ford");
	car->PrintName();
	delete car;

	car = CarFactory::Create("Toyota");
	car->PrintName();
	delete car;
}

int main()
{
	SimpleFactorTest();

	getchar();
	return 0;
}

2.结构:

1) AbstractProduct定义简单工厂方法所创建的产品的接口。
2) ConcreteProduct实现AbstractProduct的接口。
3) Factor定义一个简单工厂方法,内部创建实际的ConcreteProduct,并返回基类地址。

 

3. 适用:

             主要运用于工具包或框架的开发 。

4.

优点:
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通
过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。
而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

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

而这些缺点在工厂方法模式中得到了一定的克服。

 二、工厂方法模式

1. 描述

1)工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中

2)核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。

3)这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

4)工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。
   1) 首先完全实现‘开-闭 原则’,实现了可扩展。
   2) 其次更复杂的层次结构,可以应用于产品结果复杂的场合。

 

/************* FactoryMethod.h *************/
#ifndef __FACTORY_METHOD_H
#define __FACTORY_METHOD_H
#include "Base.h"

class IFactory
{
public:
	virtual CarBase* Create() = 0;

};

class GMFactory : public IFactory
{
public:
	CarBase* Create()
	{
		return new GMCar();
	}
};

class FordFactory : public IFactory
{
public:
	CarBase* Create()
	{
		return new FordCar();
	}
};

class ToyotaFactory : public IFactory
{
public:
	CarBase* Create()
	{
		return new ToyotaCar();
	}
};

void FactoryMethodTest()
{
	IFactory* pFactory = NULL;
	CarBase*  pCar     = NULL;

	GMFactory gmFactory;
	FordFactory fordFactory;
	ToyotaFactory toyotaFactory;

	pFactory = &gmFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pFactory = &fordFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pFactory = &toyotaFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pCar = NULL;
	pFactory = NULL;

}

#endif

  main.cpp

#include "FactoryMethod.h"

int main()
{
	//SimpleFactorTest();
	FactoryMethodTest();

	getchar();
	return 0;
}

2. 意图:定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例化延迟到其子类对象的创建过程。

1) AbstractProduct定义简单工厂方法所创建的产品的接口。
2) ConcreteProduct实现AbstractProduct的接口。
3) AbstractFactory声明了一个工厂方法,该方法返回一个AbstractProduct对象。
4) ConcreteFactory实现了基类的方法,内部创建对象的ConcreteProduct,返回的是基类AbstractProduct对象

 

 

3. 适用

主要应用与两种情况:

第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。

第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程对于使用者来说是透明的(即将具体怎样调用哪个工厂生产隐藏掉,例如Linux下调用这个,window下调用另一个工厂)。

4.优缺点

 使用工厂方法虽然进行了解耦,使程序更加灵活,但是也带来了类膨胀的后果。C++的模板机制允许我们使用简单工厂的方式来解决非模板简单工厂的缺陷。

5.类模板改写

 

/************* TCarFactory.h ****************/
#ifndef _TFACTORY_H
#define _TFACTORY_H
#include "Base.h"

template<class T>
class TCarFactory
{
public:
	T* Create()
	{
		return new T();
	}
};

class STCarFactory
{
public:
	template<class T>
	static T* Create()
	{
		return new T();
	}
};

class STCarBaseFactory
{
public:
	template<class T> 
	static CarBase* Create()
	{
		return new T();
	}
};

void TCarFactoryTest()
{
	CarBase* pCar = NULL;

	TCarFactory<GMCar> gmFactory;
	TCarFactory<FordCar> fordFactory;
	TCarFactory<ToyotaCar> toyotaFactory;

	pCar = gmFactory.Create();
	pCar->PrintName();
	delete pCar;


	pCar = fordFactory.Create();
	pCar->PrintName();
	delete pCar;


	pCar = toyotaFactory.Create();
	pCar->PrintName();
	delete pCar;

	pCar = NULL;
}

void STCarFactoryTest()
{
	CarBase* pCar = NULL;
	pCar = STCarFactory::Create<GMCar>();
	pCar->PrintName();
	delete pCar;


	pCar = STCarFactory::Create<FordCar>();
	pCar->PrintName();
	delete pCar;


	pCar = STCarFactory::Create<ToyotaCar>();
	pCar->PrintName();
	delete pCar;

	pCar = NULL;
}

void STCarBaseFactoryTest()
{
	CarBase* pCar = NULL;
	pCar = STCarBaseFactory::Create<GMCar>();
	pCar->PrintName();
	delete pCar;


	pCar = STCarBaseFactory::Create<FordCar>();
	pCar->PrintName();
	delete pCar;


	pCar = STCarBaseFactory::Create<ToyotaCar>();
	pCar->PrintName();
	delete pCar;

	pCar = NULL;
}

#endif

  main.h

#include "TCarFactory.h"

int main()
{
	//SimpleFactorTest();
	//FactoryMethodTest();
	TCarFactoryTest();
	STCarFactoryTest();
	STCarBaseFactoryTest();

	getchar();
	return 0;
}

6. 工厂方法进一步应用

现在假设我们要生产一辆组装车,该车由引擎,底盘以及轮子组合而成,在不修改我们前面的代码的基础上进行扩展。
代码如下:

增加AssemblingCar继承CarBase,增加AssemblingCarFactory继承IFactory

工厂方法符合了面向对象中的

开放-封闭原则(OCP)。关于开发封闭原则,其核心的思想是软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。

#ifndef __FACTORY_METHOD_H
#define __FACTORY_METHOD_H
#include "Base.h"

class IFactory
{
public:
	virtual CarBase* Create() = 0;

};

class GMFactory : public IFactory
{
public:
	CarBase* Create()
	{
        return new GMCar();
	}
};

class FordFactory : public IFactory
{
public:
	CarBase* Create()
	{
		return new FordCar();
	}
};

class ToyotaFactory : public IFactory
{
public:
	CarBase* Create()
	{
		return new ToyotaCar();
	}
};

/************************************************************************/
/*                         增加代码                                     */
/************************************************************************/

class Engine
{
public:
	Engine()
	{
		printf("组装引擎\n");
	}

	~Engine()
	{
		printf("引擎析构\n");
	}
};

class UnderPan
{
public:
	UnderPan()
	{
		printf("组装底盘\n");
	}

	~UnderPan()
	{
       printf("底盘析构\n");
	}
};

class Wheel
{
public:
	Wheel()
	{
		printf("组装轮子\n");
	}

	~Wheel()
	{
		printf("轮子析构\n");
	}
};

class AssemblingCar : public CarBase
{
public:
    AssemblingCar(Engine* pEngine,UnderPan* pPan,Wheel* pWheel)
	{
		m_ptrEngine.reset(pEngine);
		m_ptrUnderPan.reset(pPan);
		m_ptrWheel.reset(pWheel);
	}

	void PrintName()
	{
		printf("AssemblingCar由引擎,底盘以及轮子组装而成\n");
	}
private:
	tr1::shared_ptr<Engine>   m_ptrEngine;
	tr1::shared_ptr<UnderPan> m_ptrUnderPan;
	tr1::shared_ptr<Wheel>    m_ptrWheel;
};

class AssemblingCarFactory : public IFactory
{
public:
     CarBase* Create()
	{
        return new AssemblingCar(new Engine,new UnderPan,new Wheel);
	}
};

void AssemblingCarFactoryTest()
{
	AssemblingCarFactory factory;
	CarBase* pCar = factory.Create();
	pCar->PrintName();
	delete pCar;
	pCar = NULL;
}

void FactoryMethodTest()
{
	IFactory* pFactory = NULL;
	CarBase*  pCar     = NULL;

    GMFactory gmFactory;
    FordFactory fordFactory;
    ToyotaFactory toyotaFactory;

	pFactory = &gmFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pFactory = &fordFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pFactory = &toyotaFactory;
	pCar = pFactory->Create();
	pCar->PrintName();
	delete pCar;

	pCar = NULL;
	pFactory = NULL;

}
#endif

 三、抽象工厂

 我们继续以汽车生产商生产汽车的例子来进一步描述抽象工厂模式。

前面的例子各个汽车厂商仅仅生产一种产品(CarBase)。事实上我们发现各个汽车厂商生产的产品线非常庞大,单单轿车(Car)可分为商务轿车和跑车等等。而前面论述的简单工厂或工厂方法仅仅只能生产一种产品,如果要生产一系列产品,如何办呢?
这时候我们就需要引入抽象工厂设计模式

1) 当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品!
2) 抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。
3) 每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
4) 每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构(产品族)。

#ifndef __ABSTRACT_FACTORY_H
#define __ABSTRACT_FACTORY_H
#include "Base.h"

class BusinessCarBase : public CarBase
{
protected:
	BusinessCarBase(){}
	BusinessCarBase(const string& name) : CarBase(name){}
};

class SportCarBase : public CarBase
{
protected:
    SportCarBase(){}
	SportCarBase(const string& name) : CarBase(name){}
};

class BMWBusinessCar : public BusinessCarBase
{
public:
	BMWBusinessCar():BusinessCarBase("宝马汽车公司")
	{
	}

	void PrintName()
	{
       printf("宝马商务车\n");
	   BusinessCarBase::PrintName();
	}
};

class BMWSportCar : public SportCarBase
{
public:
	BMWSportCar():SportCarBase("宝马汽车公司")
	{
	}

	void PrintName()
	{
       printf("宝马轿跑车\n");
	   SportCarBase::PrintName();
	}
};

class BenzBusinessCar : public BusinessCarBase
{
public:
	BenzBusinessCar():BusinessCarBase("奔驰汽车公司")
	{
	}

	void PrintName()
	{
       printf("奔驰商务车\n");
	   BusinessCarBase::PrintName();
	}
};

class BenzSportCar : public SportCarBase
{
public:
	BenzSportCar():SportCarBase("奔驰汽车公司")
	{
	}

	void PrintName()
	{
       printf("奔驰轿跑车\n");
	   SportCarBase::PrintName();
	}
};

class IAbstractFactory
{
public:
	virtual BusinessCarBase* CreateBusinessCar() = 0;
	virtual SportCarBase*    CreateSportCar() = 0;
};

class BMWFactory : public IAbstractFactory
{
public:
	BusinessCarBase* CreateBusinessCar()
	{
		return new BMWBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return new BMWSportCar();
	}
};

class BenzFactory : public IAbstractFactory
{
public:
	BusinessCarBase* CreateBusinessCar()
	{
		return new BenzBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return new BenzSportCar();
	}
};

void AbstractFactoryTest()
{
   BusinessCarBase* pBCar = NULL;
   SportCarBase*    pSCar = NULL;

   BMWFactory bmwFactory;
   BenzFactory benzFacory;

   pBCar = bmwFactory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = bmwFactory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;

   pBCar = benzFacory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = benzFacory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;
}

#endif

  main.h

#include "TCarFactory.h"
#include "AbstractFactory.h"

int main()
{
	//SimpleFactorTest();
	//FactoryMethodTest();
	//TCarFactoryTest();
	//STCarFactoryTest();
	//STCarBaseFactoryTest();
	AbstractFactoryTest();

	getchar();
	return 0;
}

对抽象工厂模式的扩展

以工厂生产汽车为例子,假设我们现在要增加一种产品族:卡车。奔驰和宝马公司都要生产卡车

#ifndef __ABSTRACT_FACTORY_H
#define __ABSTRACT_FACTORY_H
#include "Base.h"

class BusinessCarBase : public CarBase
{
protected:
	BusinessCarBase(){}
	BusinessCarBase(const string& name) : CarBase(name){}
};

class SportCarBase : public CarBase
{
protected:
    SportCarBase(){}
	SportCarBase(const string& name) : CarBase(name){}
};

class BMWBusinessCar : public BusinessCarBase
{
public:
	BMWBusinessCar():BusinessCarBase("宝马汽车公司")
	{
	}

	void PrintName()
	{
       printf("宝马商务车\n");
	   BusinessCarBase::PrintName();
	}
};

class BMWSportCar : public SportCarBase
{
public:
	BMWSportCar():SportCarBase("宝马汽车公司")
	{
	}

	void PrintName()
	{
       printf("宝马轿跑车\n");
	   SportCarBase::PrintName();
	}
};

class BenzBusinessCar : public BusinessCarBase
{
public:
	BenzBusinessCar():BusinessCarBase("奔驰汽车公司")
	{
	}

	void PrintName()
	{
       printf("奔驰商务车\n");
	   BusinessCarBase::PrintName();
	}
};

class BenzSportCar : public SportCarBase
{
public:
	BenzSportCar():SportCarBase("奔驰汽车公司")
	{
	}

	void PrintName()
	{
       printf("奔驰轿跑车\n");
	   SportCarBase::PrintName();
	}
};

class IAbstractFactory
{
public:
	virtual BusinessCarBase* CreateBusinessCar() = 0;
	virtual SportCarBase*    CreateSportCar() = 0;
};

class BMWFactory : public IAbstractFactory
{
public:
	BusinessCarBase* CreateBusinessCar()
	{
		return new BMWBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return new BMWSportCar();
	}
};

class BenzFactory : public IAbstractFactory
{
public:
	BusinessCarBase* CreateBusinessCar()
	{
		return new BenzBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return new BenzSportCar();
	}
};

/*现在要重新增加新的产品族Truck*/

class TruckCarBase : public CarBase
{
protected:
    TruckCarBase(){}
	TruckCarBase(const string& name) : CarBase(name){}
};

class IExtendedAbstractFactory : public IAbstractFactory
{
public:
	virtual TruckCarBase* CreateTruckCar() = 0;
};


class BMWTruckCar : public TruckCarBase
{
public:
	BMWTruckCar():TruckCarBase("宝马汽车公司")
	{
	}

	void PrintName()
	{
		printf("宝马卡车\n");
		TruckCarBase::PrintName();
	}
};

class BenzTruckCar : public TruckCarBase
{
public:
	BenzTruckCar():TruckCarBase("奔驰汽车公司")
	{
	}

	void PrintName()
	{
       printf("奔驰卡车\n");
	   TruckCarBase::PrintName();
	}
};

class BenzExtendedFactory : public IExtendedAbstractFactory
{
public:
    public:
	BusinessCarBase* CreateBusinessCar()
	{
		return factory.CreateBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return factory.CreateSportCar();
	}

	TruckCarBase* CreateTruckCar()
	{
		return new BenzTruckCar();
	}

protected:
	/*
	我们使用接口继承
    但使用已经实现的BenzFactory进行扩展。
	经典的使用对象的组合而不是继承方式进行扩展
	*/
    BenzFactory factory;
	/*
	如果假设针对一个DLL,并且该DLL导出的都是接口的话
	我们可以使用IBenzFactory* pIBenzFactory进行扩展。
	*/
};

class BMWExtendedFactory : public IExtendedAbstractFactory
{
public:
    public:
	BusinessCarBase* CreateBusinessCar()
	{
		return factory.CreateBusinessCar();
	}

	SportCarBase*    CreateSportCar()
	{
		return factory.CreateSportCar();
	}

	TruckCarBase* CreateTruckCar()
	{
		return new BMWTruckCar();
	}

protected:
	/*
	我们使用接口继承
    但使用已经实现的BenzFactory进行扩展。
	经典的使用对象的组合而不是继承方式进行扩展
	*/
    BMWFactory factory;
	/*
	如果假设针对一个DLL,并且该DLL导出的都是接口的话
	我们可以使用IBenzFactory* pIBenzFactory进行扩展。
	*/
};



void AbstractFactoryTest()
{
   BusinessCarBase* pBCar = NULL;
   SportCarBase*    pSCar = NULL;

   BMWFactory bmwFactory;
   BenzFactory benzFacory;

   pBCar = bmwFactory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = bmwFactory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;

   pBCar = benzFacory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = benzFacory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;
}

void ExtendedAbstractFactoryTest()
{
   BusinessCarBase* pBCar = NULL;
   SportCarBase*    pSCar = NULL;
   TruckCarBase*    pTCar = NULL;

   BMWExtendedFactory bmwFactory;
   BenzExtendedFactory benzFacory;

   pBCar = bmwFactory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = bmwFactory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;

   pTCar = bmwFactory.CreateTruckCar();
   pTCar->PrintName();
   delete pTCar;

   pBCar = benzFacory.CreateBusinessCar();
   pBCar->PrintName();
   delete pBCar;

   pSCar = benzFacory.CreateSportCar();
   pSCar->PrintName();
   delete pSCar;

   pTCar = benzFacory.CreateTruckCar();
   pTCar->PrintName();
   delete pTCar;
}
#endif

  main.h

#include "TCarFactory.h"
#include "AbstractFactory.h"

int main()
{
	//SimpleFactorTest();
	//FactoryMethodTest();
	//TCarFactoryTest();
	//STCarFactoryTest();
	//STCarBaseFactoryTest();
	//AbstractFactoryTest();
	ExtendedAbstractFactoryTest();

	getchar();
	return 0;
}

四、面向对象七大原则

设计模式目的:高内聚,低耦合

1) 单一职责原则 (SRP,Single Responsibility Principle)类的职责要单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。

2) 开放封闭原则 (OCP,Open For Extension, Closed For Modification Principle) 类的改动是通过增加代码进行的,而不是修改源代码。

3) 依赖倒置原则 (DIP,Dependence Inversion Principle)依赖于抽象(接口),不要依赖具体的实现(类),也就是针对接口编程。

4) 接口隔离原则 (ISP,Interface Segegation Principle)不应该强迫客户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去。

5) 里氏替换原则 (LSP, Liskov Substitution Principle)任何抽象类出现的地方都可以用他的实现类进行替换。实际就是虚拟机制,语言级别实现面向对象功能。

6) 优先使用组合而不是继承原则(CARP,Composite/Aggregate Reuse Principle)如果使用继承,会导致父类的任何变换都可能影响到子类的行为。如果使用对象组合,就降低了这种依赖关系。

7) 迪米特法则(LOD,Law of Demeter) 一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。
例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样其他模块不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发生改变时,不会影响其他模块的使用。(黑盒原理)

五、总结

简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力,使用模板简单工厂可以任意添加新产品)

工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)

抽象工厂 :用来生产不同产品族的全部产品。       (支持增加产品族,但比较复杂)  

 

 

 

 

 

 

 

posted on 2013-12-15 18:50  奎哥  阅读(779)  评论(0编辑  收藏  举报