C++设计模式——抽象工厂模式
概述
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
场景分析
我们依旧用红色警戒的例子,在工厂方法模式中,我们用工厂方法模式克服了简单工厂中存在的违背开闭原则的缺点,但是同时也引出了另外一个问题,如果我们需要生产的产品变多的时候,那产品所对应的工厂也会越来越多,这样明显加大了代码的复杂程度。假如我们现在不仅仅要派中国兵,美国兵,苏联兵,我们还需要实现派出中国坦克,美国坦克和苏联坦克的功能,那在简单工厂模式中,就必须通过违反开闭原则,在工厂类中增加逻辑判断。在工厂方法模式中,则要创建中国坦克工厂、美国坦克工厂、苏联坦克工厂等工厂。那在抽象工厂模式中,我们怎么实现呢?
类图描述
AbstractFaactory:抽象工厂类,声明用于创建抽象产品的接口。
ChineseFactory…:具体工厂类,实现用于创建具体产品的接口。
Soldiers、Tank: 抽象产品类,声明士兵所需要的公共接口。
ChineseSoldiers\ChineseTabk:具体产品类,实现产品所需要的接口。
实现
//Tank
#ifndef TANK_H_
#define TANK_H_
#include <iostream>
class Tank
{
public:
virtual std::string GetTank() = 0;
};
class ChineseTank: public Tank
{
public:
virtual std::string GetTank()
{
return "Chinese Tank";
}
};
class AmericanTank: public Tank
{
public:
virtual std::string GetTank()
{
return "American Tank";
}
};
class SovietTank: public Tank
{
public:
virtual std::string GetTank()
{
return "Soviet Tank";
}
};
#endif
//Soldiers
#ifndef PRODUCT_H_
#define PRODUCT_H_
#include <iostream>
class Soldiers
{
public:
virtual std::string GetSoldiers() = 0;
};
class ChineseSoldiers: public Soldiers
{
public:
virtual std::string GetSoldiers()
{
return "Chinese Soldiers";
}
};
class AmericanSoldiers: public Soldiers
{
public:
virtual std::string GetSoldiers()
{
return "American Soldiers";
}
};
class SovietSoldiers: public Soldiers
{
public:
virtual std::string GetSoldiers()
{
return "Soviet Soldiers";
}
};
#endif
//AbstractFaactory.h
#ifndef ABSTRACT_FACTORY_H_
#define ABSTRACT_FACTORY_H_
#include "Soldiers.h"
#include "Tank.h"
class AbstractFactory
{
public:
enum FactoryType{Chinese,American,Soviet};
public:
virtual Soldiers* CreateSoldiers() = 0;
virtual Tank* CreateTank() = 0;
static AbstractFactory* CreateFactory(FactoryType type);
};
class ChineseFactory: public AbstractFactory
{
public:
virtual Soldiers* CreateSoldiers()
{
return new ChineseSoldiers();
}
virtual Tank* CreateTank()
{
return new ChineseTank();
}
};
class AmricanFactory: public AbstractFactory
{
public:
virtual Soldiers* CreateSoldiers()
{
return new AmericanSoldiers();
}
virtual Tank* CreateTank()
{
return new AmericanTank();
}
};
class SovietFactory: public AbstractFactory
{
public:
virtual Soldiers* CreateSoldiers()
{
return new SovietSoldiers();
}
virtual Tank* CreateTank()
{
return new SovietTank();
}
};
#endif
//AbstractFaactory.cpp
#include "AbstractFactory.h"
AbstractFactory* AbstractFactory::CreateFactory( FactoryType type )
{
AbstractFactory* factory = nullptr;
switch (type)
{
case FactoryType::American:
factory = new AmricanFactory();
break;
case FactoryType::Chinese:
factory = new ChineseFactory();
break;
case FactoryType::Soviet:
factory = new SovietFactory();
break;
default:
break;
}
return factory;
}
//main.cpp
#include <iostream>
#include "AbstractFactory.h"
using namespace std;
#ifndef SAFE_DELETE
#define SAFE_DELETE(Obj) \
{\
if (Obj) \
{\
delete (Obj); \
(Obj)=NULL;\
}\
}
#endif SAFE_DELETE
int main()
{
AbstractFactory* ChFactory = AbstractFactory::CreateFactory(AbstractFactory::FactoryType::Chinese);
Soldiers* ChSoldiers = ChFactory->CreateSoldiers();
Tank* ChTank = ChFactory->CreateTank();
std::string strChSoldiers = ChSoldiers->GetSoldiers();
std::string strChTank = ChTank->GetTank();
cout << "Chinese Soldiers Factory : " << strChSoldiers.c_str() << endl;
cout << "Chinese Tank Factory : " << strChTank.c_str() << endl;
SAFE_DELETE(ChFactory);
SAFE_DELETE(ChSoldiers);
SAFE_DELETE(ChTank);
AbstractFactory* AmFactory = AbstractFactory::CreateFactory(AbstractFactory::FactoryType::American);
Soldiers* AmSoldiers = AmFactory->CreateSoldiers();
Tank* AmTank = AmFactory->CreateTank();
std::string strAmSoldiers = AmSoldiers->GetSoldiers();
std::string strAmTank = AmTank->GetTank();
cout << "American Soldiers Factory : " << strAmSoldiers.c_str() << endl;
cout << "American Tank Factory : " << strAmTank.c_str() << endl;
SAFE_DELETE(AmFactory);
SAFE_DELETE(AmSoldiers);
SAFE_DELETE(AmTank);
AbstractFactory* SoFactory = AbstractFactory::CreateFactory(AbstractFactory::FactoryType::Soviet);
Soldiers* SoSoldiers = SoFactory->CreateSoldiers();
Tank* SoTank = SoFactory->CreateTank();
std::string strSoSoldiers = SoSoldiers->GetSoldiers();
std::string strSoTank = SoTank->GetTank();
cout << "Soviet Soldiers Factory : " << strSoSoldiers.c_str() << endl;
cout << "Soviet Tank Factory : " << strSoTank.c_str() << endl;
SAFE_DELETE(SoFactory);
SAFE_DELETE(SoSoldiers);
SAFE_DELETE(SoTank);
return 0;
}
优缺点
优点:
调用者无需知道产品创建的流程,只需要创建产品所需要的工厂即可。
适用于产品或者产品类型较多的情况。模式的灵活性更强。
缺点
很明显违背了开闭原则,当有新的工厂添加的时候,必须要在创建工厂的方法中修改代码。
如果产品再多,结构臃肿,难于管理。
适应场景
- 适用于产品族较多的时候的产品的创建。