一、意图
提供一个接口一创建一系列相关或相互依赖的对象,而无需指定它们具体的类。
二、UML
三、问题
假设我们开发一些列产品,例如:椅子Chair、沙发Sofa和咖啡桌CoffeTable。现在我们有多种产品的变体:如现代Modern、维多利亚Vectorian、装饰风艺术ArtDeco等风格来生成与椅子、沙发和咖啡桌。
为了确保产品生成的风格一致,同时减少增添新产品或新风格时的代码修改量,我们引入抽象工厂模式。
四、解决方案
首先,抽象工厂模式建议为系列中的每件产品明确声明接口(例如椅子、 沙发或咖啡桌)。然后,确保所有产品变体都继承这些接口。例如,所有风格的椅子都实现椅子接口;所有风格的咖啡桌都实现咖啡桌接口,以此类推。
接下来,我们需要声明抽象工厂——包含系列中所有产品构造方法的接口。例如 createChair创建椅子 、createSofa创建沙发和createCoffeeTable创建咖啡桌。这些方法必须返回抽象产品类型,即我们之前抽取的那些接口:椅子,沙发和咖啡桌等等。
那么该如何处理产品变体呢?对于系列产品的每个变体,我们都将基于抽象工厂接口创建不同的工厂类。每个工厂类都只能返回特定类别的产品,例如,现代家具工厂ModernFurnitureFactory只能创建现代椅子ModernChair、现代沙发ModernSofa和现代咖啡桌ModernCoffeeTable对象。
客户端代码可以通过相应的抽象接口调用工厂和产品类。 你无需修改实际客户端代码, 就能更改传递给客户端的工厂类, 也能更改客户端代码接收的产品变体。
假设客户端想要工厂创建一把椅子。客户端无需了解工厂类,也不用管工厂类创建出的椅子类型。无论是现代风格,还是维多利亚风格的椅子,对于客户端来说没有分别,它只需调用抽象椅子接口就可以了。 这样一来,客户端只需知道椅子以某种方式实现了sitOn坐下方法就足够了。此外,无论工厂返回的是何种椅子变体,它都会和由同一工厂对象创建的沙发或咖啡桌风格一致。
最后一点说明: 如果客户端仅接触抽象接口, 那么谁来创建实际的工厂对象呢? 一般情况下, 应用程序会在初始化阶段创建具体工厂对象。 而在此之前, 应用程序必须根据配置文件或环境设定选择工厂类别。
五、实例
#include <iostream>
#include <map>
#include <memory>
/* ==============================*/
/* ===== Product 00 : Chair =====*/
/* ==============================*/
class AbstractChair
{
public:
virtual ~AbstractChair() {}
virtual std::string GetChairName() const = 0;
};
class ArtDecoChair : public AbstractChair
{
public:
std::string GetChairName() const override
{
return "Art Deco Chair";
}
};
class VictorianChair : public AbstractChair
{
public:
std::string GetChairName() const override
{
return "Victorian Chair";
}
};
class ModernChair : public AbstractChair
{
public:
std::string GetChairName() const override
{
return "Modern Chair";
}
};
/* =============================*/
/* ===== Product 02 : Sofa =====*/
/* =============================*/
class AbstractSofa
{
public:
virtual ~AbstractSofa() {}
virtual std::string GetSofaName() const = 0;
};
class ArtDecoSofa : public AbstractSofa
{
std::string GetSofaName() const override
{
return "Art Deco Sofa";
}
};
class VictorianSofa : public AbstractSofa
{
std::string GetSofaName() const override
{
return "Victorian Sofa";
}
};
class ModernSofa : public AbstractSofa
{
std::string GetSofaName() const override
{
return "Modern Sofa";
}
};
/* ===================*/
/* ===== Factory =====*/
/* ===================*/
class AbstractFactory
{
public:
virtual AbstractChair* CreateChair() const = 0;
virtual AbstractSofa* CreateSofa() const = 0;
};
class ArtDecoFactory : public AbstractFactory
{
public:
AbstractChair* CreateChair() const override
{
return new ArtDecoChair();
}
AbstractSofa* CreateSofa() const override
{
return new ArtDecoSofa();
}
};
class VictorianFactory : public AbstractFactory
{
public:
AbstractChair* CreateChair() const override
{
return new VictorianChair();
}
AbstractSofa* CreateSofa() const override
{
return new VictorianSofa();
}
};
class ModernFactory : public AbstractFactory
{
AbstractChair* CreateChair() const override
{
return new ModernChair();
}
AbstractSofa* CreateSofa() const override
{
return new ModernSofa();
}
};
void Cilent_ShowProduct(const AbstractFactory& p_factory)
{
const AbstractChair* chair = p_factory.CreateChair();
const AbstractSofa* sofa = p_factory.CreateSofa();
std::cout << chair->GetChairName() << std::endl;
std::cout << sofa->GetSofaName() << std::endl;
delete chair;
delete sofa;
}
int main()
{
std::cout << "now is Art Deco Factory" << std::endl;
const ArtDecoFactory* artdecoFactory = new ArtDecoFactory();
Cilent_ShowProduct(*artdecoFactory);
return 0;
}