C++ 设计模式之抽象工厂模式

回顾之前的设计模式,简单工厂模式将所有逻辑都封装在工厂类中,工厂根据客户提供的产品名字创建对应产品的对象实例;工厂模式将产品的创建过程放到了具体工厂类中,每一个工厂可以创建一个具体产品,由此可能会创建许多工厂类。很多时候,一个工厂不只是生产一种产品,而是生产一类产品,比如一个体育用品工厂,可以生产篮球、足球、排球等多种产品。此时我们可以把这些相关的产品归纳为一个 “产品族”,由同一个工厂来生产,这即是今天要学习的抽象工厂模式。

1. 抽象工厂模式简介

抽象工厂模式是常用的创建型设计模式之一。而今天要学习的抽象工厂模式,其抽象程度更高,每一个具体工厂可以生产一组相关的具体产品对象

抽象工厂模式定义:

抽象工厂模式:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

简言之,一个工厂可以提供创建多种产品的接口,而无需向工厂方法一样,为每一个产品都提供一个具体工厂。


2. 抽象工厂模式结构

抽象工厂模式与工厂模式结构类似。不同之处在于,一个具体的工厂可以生产多种同类相关的产品:

  • 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
  • 具体工厂(ConcreteFactory):生产具体的产品
  • 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
  • 具体产品(ConcreteProduct):具体的产品类

抽象工厂模式 UML 类图如下:
在这里插入图片描述
结合抽象工厂模式定义和 UML,可以看到具体工厂 COncreteFactory_A 可以生产两种产品,分别是 ConcreteProduct_A_1 和 ConcreteProduct_A_2,另一个工厂 COncreteFactory_B 同理。客户端使用时,需要声明一个抽象工厂 AbstractFactory 和 两个抽象产品 AbstractProduct。


3. 抽象工厂模式实例代码

考虑如下一个场景,如下图:

Jungle想要进行户外运动,它可以选择打篮球和踢足球。但这次Jungle不想弄脏原本穿的T恤,所以Jungle还需要穿球衣,打篮球就穿篮球衣,踢足球就穿足球衣。篮球保管室可以提供篮球和篮球衣,足球保管室可以提供足球和足球衣。Jungle只要根据心情去某个保管室,就可以换上球衣、拿上球,然后就可以愉快地玩耍了。
在这里插入图片描述
对应的 UML 实例图如下:
在这里插入图片描述


3.1 定义产品类

3.1.1 产品类 Ball
  • 抽象产品类 AbstractBall,球类的基类,定义抽象方法 play
class AbstractBall{
public:
    AbstractBall(){}
    // 抽象方法
    void play(){}
};
  • 具体产品类,为 BasketBall,具体实现方法 play
class Basketball : public AbstractBall{
public:
    Basketball()
    {
        play();
    }
    void play()
    {
        cout << "play Basketball" << endl;
    }
};
3.1.2 产品类 Shirt
  • 抽象产品类 AbstractShirt:球衣类的基类,定义抽象方法 wearShirt
class AbstractShirt{
public:
    AbstractShirt(){}
    // 抽象方法
    void wearShirt(){}
};

  • 具体产品类 BasketballShirt,具体实现方法 wearShirt
class BasketballShirt : public AbstractShirt{
public:
    BasketballShirt()
    {
        wearShirt();
    }
    void wearShirt()
    {
        cout << "wear Basketball Shirt\n";
    }
};

3.2 定义工厂类

  • 定义抽象工厂 AbstractFactory,声明两个方法 getBall 和 getShirt
class AbstractFactory{
public:
    AbstractFactory(){}
    virtual AbstractBall *getBall() = 0;
    virtual AbstractShirt *getShirt() = 0;
};
  • 定义具体工厂 BasketBallFactory,重新实现两个方法 getBall 和 wearShirt
class BasketballFactory : public AbstractFactory{
public:
    BasketballFactory()
    {
        cout << "BasketballFactory\n";
    }
    AbstractBall *getBall()
    {
        cout << "get basketball\n";
        return new Basketball();
    }
    AbstractShirt *getShirt()
    {
        cout << "get basketball shirt\n";
        return new BasketballShirt();
    }
};

3.3 客户端使用方法实例

#include <iostream>
#include "AbstractFactory.h"
using namespace std;
void test4()
{
    AbstractBall *b = nullptr;
    AbstractShirt *s = nullptr;
    AbstractFactory *f = nullptr;

    f = new BasketballFactory();
    f->getBall();
    f->getShirt();
}
int main()
{
    test4();
    return 0;
}

3.4 效果

在这里插入图片描述


4. 抽象工厂模式总结

抽象工厂模式中,如果需要新增加一个系列的产品,比如足球系列,则需要增加一组新的具体产品类(抽象和具体)并提供给一个对应的工厂类即可。但是,如果要在已有的产品族里增加另外一个产品,比如在打篮球,除了需要篮球和篮球衣之外,还想一双篮球鞋,这时候该怎么办呢?是不是要去修改 BasketballFactory 呢?由此,总结了抽象模式特点:

优点:
抽象工厂模式除了具有工厂模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少都存在一定的联系,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

缺点:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

适用环境:

  • 一系列/一族产品需要被同时使用,适合使用抽象工厂模式
  • 产品结构稳定,设计完成之后不会向系统中新增或者剔除某个产品
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值