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


在介绍完简单工厂模式时,总结出了简单工厂模式存在最大的问题就是违背了 “开闭原则”,每当增加新的产品时,需要修改工厂类的逻辑。为了规避这种不足,同时很好的利用简单工厂模式的优点,本节将声情并茂地为您奉上工厂方法模式。

1. 工厂模式简介

简单工厂模式中,每增加一个具体产品,就需要修改工厂类内部的判断逻辑。为了不修改工厂类,遵循开闭原则,工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂,每一个工厂只生产特定的产品

工厂方法模式定义:

工厂方法模式:
定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类

2. 工厂模式结构

从工厂模式简介中,可以知道该模式有以下几种角色:

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

工厂方法模式 UML 类图如下:
在这里插入图片描述

3. 工厂模式代码示例

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

Jungle想要进行户外运动,它可以选择打篮球、踢足球或者玩排球。和上一次的体育保管室不同,这次分别由篮球保管室、足球保管室和排球保管室,Jungle只需直接去相应的保管室就可以拿到对应的球!然后Jungle就可以愉快地玩耍了。
在这里插入图片描述
对应的UML实例图如下图:
在这里插入图片描述

3.1 定义抽象产品类AbstractProduct,方法不提供实现

// 抽象产品类
class AbstractProduct{
public:
    AbstractProduct(){}
    // 抽象方法
    void printName(){}
    void play(){}
};

3.2 定义三个具体产品类

// 定义三个产品类 basketball
class Basketball  : public AbstractProduct{
public:
    Basketball(){
        printName();
        play();
    }
    // 具体实现方法
    void printName()
    {
        cout << "Jungle get Basketball\n";
    }
    void play()
    {
        cout << "Jungle play Basketball\n";
    }
};
// 定义三个产品类 Football
class Football  : public AbstractProduct{
public:
    Football(){
        printName();
        play();
    }
    // 具体实现方法
    void printName()
    {
        cout << "Jungle get Football\n";
    }
    void play()
    {
        cout << "Jungle play Football\n";
    }
};
// 定义三个产品类 Volleyball
class Volleyball  : public AbstractProduct{
public:
    Volleyball(){
        printName();
        play();
    }
    // 具体实现方法
    void printName()
    {
        cout << "Jungle get Volleyball\n";
    }
    void play()
    {
        cout << "Jungle play Volleyball\n";
    }
};

3.3 定义抽象工厂类AbstractFactory,方法为纯虚方法

// 抽象工厂类
class AbstractFactory{
public:
    AbstractFactory(){}
    // 提供公共的方法
    virtual AbstractProduct *getSportProduct() = 0;
};

3.4 定义三个具体工厂类

// 具体工厂类
class BasketballFactory : public AbstractFactory{
public:
    BasketballFactory()
    {
        cout << "BasketballFactory\n";
    }
    AbstractProduct *getSportProduct()
    {
        cout << "basketball" << endl;
        return new Basketball();
    }
};
// 具体工厂类
class FootballFactory : public AbstractFactory{
public:
    FootballFactory()
    {
        cout << "BasketballFactory\n";
    }
    AbstractProduct *getSportProduct()
    {
        cout << "football" << endl;
        return new Football();
    }
};
// 具体工厂类
class VolleyballFactory : public AbstractFactory{
public:
    VolleyballFactory()
    {
        cout << "VolleyballFactory\n";
    }
    AbstractProduct *getSportProduct()
    {
        cout << "volleyball" << endl;
        return new Volleyball();
    }
};

3.5 客户端使用方法示例

#include <iostream>
#include "Factory.h"
using namespace std;

void test2()
{
    AbstractFactory *f = nullptr;
    AbstractProduct *p = nullptr;

    f = new BasketballFactory();
    p = f->getSportProduct();
    cout << endl;

     f = new FootballFactory();
    p = f->getSportProduct();
    cout << endl;

     f = new VolleyballFactory();
    p = f->getSportProduct();
}
int main()
{
    test2();
    return 0;
}

3.6 效果

在这里插入图片描述


工厂模式总结

如果Jungle想玩棒球(Baseball),只需要增加一个棒球工厂(BaseballFacory),然后在客户端代码中修改具体工厂类的类名,而原有的类的代码无需修改。由此可看到,相较简单工厂模式,工厂方法模式更加符合开闭原则。工厂方法是使用频率最高的设计模式之一,是很多开源框架和API类库的核心模式。


优点:

  • 工厂模式用于床创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需要关心产品对应的工厂;
  • 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂模式的关键;
  • 新加入产品时,无需修改原有代码,增加了系统的可扩展性符合开闭原则

缺点:

  • 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销。
  • 工厂和产品都引入了抽象层,客户端代码中均使用抽象层,增加了系统的抽象层次和理解难度。

适用环境:

  • 客户端不需要知道它所需要创建的对象的类;
  • 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值