一、抽象工厂模式简介
抽象工厂模式是所有形态的工厂模式中最为抽象和具有一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。例如现实生活中,水果的种类繁多,众多水果中,桃子也分很多种类,还分地域,比如北方的猕猴桃,南方的猕猴桃等。而抽象工厂模式就是模拟现实中的分类,实现生产一个产品组(相对工厂模式,抽象工厂模式可以生产一个产品的族)。抽象工厂模式的核心思想是定义一个用于创建一系列相关或相互依赖对象的接口,而不需要指定具体类。这种模式的主要优点是它将对象的创建和使用分开,使得系统更具扩展性和灵活性。
产品等级和产品族的关系
工厂模式(具体)和抽象工厂模式(抽象)的对比解释:
具体工厂在开闭原则下, 能生产香蕉/苹果/梨子; (产品等级结构)
抽象工厂:在开闭原则下, 能生产:南方香蕉/苹果/梨子 (产品族)
北方香蕉/苹果/梨子
GoF一书中对抽象工厂模式的介绍
二、抽象工厂模式的用处
1. 创建相关或相互依赖的对象
抽象工厂模式可以确保客户端只通过工厂接口创建一组相关或相互依赖的对象,而不需要了解具体的对象类。这种方法可以确保这些对象能够一起正常工作。例如,我的代码中,
NorthFactory
和SouthFactory
创建了一系列北方或南方的水果,确保了这些水果的创建和使用是一致的。2. 提供对象的跨平台支持
当系统需要在不同平台或环境下运行时(如不同操作系统、不同硬件架构等),抽象工厂模式可以提供一个统一的接口来创建对象,从而简化了跨平台的对象创建过程。例如,一个应用程序可以根据不同的操作系统(Windows、Linux、MacOS)选择不同的工厂来创建界面组件。
3. 促进系统的扩展和维护
抽象工厂模式使得系统的扩展变得更加容易。添加新的产品或产品家族时,只需要添加新的工厂类和产品类,而不需要修改现有的客户端代码。这种模式隔离了客户端与具体产品的创建细节,减少了代码的耦合度,从而使系统更容易维护和扩展。
4. 实现产品的一致性
通过将对象的创建过程封装在工厂类中,可以确保创建出的对象具有一致的风格或特点。这在需要保证一组对象之间的兼容性或一致性时尤其重要。例如,我的代码中,不同的工厂保证了北方和南方水果的一致性。
5. 支持不同的产品变种
如果一个系统需要支持多种变种的产品(例如不同风味、不同颜色的产品),抽象工厂模式可以通过不同的工厂实现来支持这些变种。每个工厂可以生成一组产品的不同变种,这样系统可以根据需求选择合适的工厂来获取相应的产品。
三、抽象工厂模式的设计方法
abstractFactory.cpp
#include <iostream>
#include <cstring>using namespace std;class Fruit
{
public:virtual void getProduct() = 0;virtual ~Fruit() = default;
};class AbstractFactory
{
public:virtual Fruit* CreateProduct(const std::string& type) = 0;virtual ~AbstractFactory() = default;
};class NorthBanana : public Fruit
{
public:void getProduct() override{std::cout << "北方香蕉 " << std::endl;}
};class NorthApple : public Fruit
{
public:void getProduct() override{std::cout << "北方苹果 " << std::endl;}
};class NorthOrange : public Fruit
{
public:void getProduct() override{std::cout << "北方橙子 " << std::endl;}
};class NorthWatermelon : public Fruit
{
public:void getProduct() override{std::cout << "北方西瓜 " << std::endl;}
};class NorthCherry : public Fruit
{
public:void getProduct() override{std::cout << "北方樱桃 " << std::endl;}
};class NorthPeach : public Fruit
{
public:void getProduct() override{std::cout << "北方桃子 " << std::endl;}
};class NorthPear : public Fruit
{
public:void getProduct() override{std::cout << "北方梨 " << std::endl;}
};class SouthBanana : public Fruit
{
public:void getProduct() override{std::cout << "南方香蕉" << std::endl;}
};class SouthApple : public Fruit
{
public:void getProduct() override{std::cout << "南方苹果" << std::endl;}
};class SouthOrange : public Fruit
{
public:void getProduct() override{std::cout << "南方橙子" << std::endl;}
};class SouthWatermelon : public Fruit
{
public:void getProduct() override{std::cout << "南方西瓜" << std::endl;}
};class SouthCherry : public Fruit
{
public:void getProduct() override{std::cout << "南方樱桃" << std::endl;}
};class SouthPeach : public Fruit
{
public:void getProduct() override{std::cout << "南方桃子" << std::endl;}
};class SouthPear : public Fruit
{
public:void getProduct() override{std::cout << "南方梨" << std::endl;}
};class NorthFactory : public AbstractFactory
{Fruit * CreateProduct(const std::string& type) override{if (type == "北方香蕉") return new NorthBanana;if (type == "北方苹果") return new NorthApple;if (type == "北方橙子") return new NorthOrange;if (type == "北方西瓜") return new NorthWatermelon;if (type == "北方樱桃") return new NorthCherry;if (type == "北方桃子") return new NorthPeach;if (type == "北方梨") return new NorthPear;return nullptr;}
};class SouthFactory : public AbstractFactory
{Fruit * CreateProduct(const std::string& type) override{if (type == "南方香蕉") return new SouthBanana;if (type == "南方苹果") return new SouthApple;if (type == "南方橙子") return new SouthOrange;if (type == "南方西瓜") return new SouthWatermelon;if (type == "南方樱桃") return new SouthCherry;if (type == "南方桃子") return new SouthPeach;if (type == "南方梨") return new SouthPear;return nullptr;}
};void doWorking()
{Fruit *fruit = nullptr;AbstractFactory *abstractfactory = nullptr;// 注册南方工厂abstractfactory = new SouthFactory;fruit = abstractfactory->CreateProduct("南方香蕉");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方苹果");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方橙子");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方西瓜");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方樱桃");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方桃子");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("南方梨");if (fruit) { fruit->getProduct(); delete fruit; }// 注销南方工厂delete abstractfactory;// 注册北方工厂abstractfactory = new NorthFactory;fruit = abstractfactory->CreateProduct("北方香蕉");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方苹果");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方橙子");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方西瓜");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方樱桃");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方桃子");if (fruit) { fruit->getProduct(); delete fruit; }fruit = abstractfactory->CreateProduct("北方梨");if (fruit) { fruit->getProduct(); delete fruit; }// 注销北方工厂delete abstractfactory;return ;
}int main(){//开工干活doWorking();return 0;
}
运行效果
抽象工厂类 (
AbstractFactory
): 这是一个抽象类,定义了一个抽象方法CreateProduct
,用于创建不同类型的Fruit
对象。具体工厂类 (
NorthFactory
和SouthFactory
): 这些类继承自AbstractFactory
,实现了CreateProduct
方法。它们负责生产具体的Fruit
对象,如NorthBanana
、SouthApple
等。抽象产品类 (
Fruit
): 这是一个抽象基类,定义了一个纯虚方法getProduct
,由具体的产品类实现。具体产品类 (
NorthBanana
,SouthApple
等): 这些类继承自Fruit
,实现了getProduct
方法,代表了具体的水果产品。客户端代码 (
doWorking
函数): 客户端代码通过抽象工厂接口创建对象,而不关心具体的实现类。它可以轻松地切换工厂(比如从南方工厂切换到北方工厂),而无需修改对象创建的代码。
在代码中,AbstractFactory
提供了创建 Fruit
对象的接口,而 NorthFactory
和 SouthFactory
分别实现了这个接口,创建北方和南方的水果。这样,如果需要添加新的工厂(比如中方工厂)或新的水果类型,只需要在相应的工厂类中添加相应的代码,而不需要修改客户端代码。
四、总结
抽象工厂模式通过提供一个创建一系列相关对象的接口,解耦了客户端代码和具体产品类,使得系统具有更好的灵活性和扩展性。它广泛应用于各种软件系统中,尤其是需要创建和管理多种相关对象的场景。