设计模式-创建型模式之-工厂模式

简单工厂模式

动机

在实际开发中,我曾遇到这样的需求:实现一个播放器,要求支持播放列表设置、播放、停止、暂停、跳转等操作。正常情况下直接实现播放器类即可,但需求要求支持不同多媒体库(如 FFmpegGStreamer)。若分别实现两种播放器类,业务逻辑中每次操作播放器时都需判断类型;若扩展到10种类型,代码将变得难以维护。
业务逻辑仅关心何时调用播放器接口,不关心具体实现,因此自然想到利用 多态:定义抽象类提取公共方法,具体类继承并实现细节。
而简单工厂模式是在多态基础上,将具体类的创建封装在专门的工厂类接口中,使用时只需指定类型,返回抽象类对象。

定义

简单工厂模式属于创建型设计模式,通过 工厂类 创建指定的具体产品类,这些产品类拥有共同的抽象基类。工厂类的创建方法通常为 static,故也称为 静态工厂方法模式
模式包含三种角色:

  • 工厂:提供静态方法,根据参数创建具体产品,以抽象产品类型返回。
  • 抽象产品:定义所有产品的公共接口,关联具体产品与工厂。
  • 具体产品:抽象产品的子类,是工厂最终创建的实例。

示例

以播放器为例,先定义抽象接口(仅示例播放/停止方法):

class PlayerInterface {
public:
    virtual void play() = 0;
    virtual void stop() = 0;
};

具体播放器类:

class FfmpegPlayer : public PlayerInterface {
public:
    void play() override {
        std::cout << "FFmpeg play" << std::endl;
    }
    void stop() override {
        std::cout << "FFmpeg stop" << std::endl;
    }
};

class GstreamerPlayer : public PlayerInterface {
public:
    void play() override {
        std::cout << "GStreamer play" << std::endl;
    }
    void stop() override {
        std::cout << "GStreamer stop" << std::endl;
    }    
};

工厂类:

class CreatePlayer {
public:
    static PlayerInterface* createPlayer(int playerType) {
        PlayerInterface* player;
        switch (playerType) {
            case 0:
                player = new FfmpegPlayer;
                break;
            case 1:
                player = new GstreamerPlayer;
                break;
            default:
                player = nullptr;
                break;
        }
        return player;
    }
};

使用示例:

int main() {
    PlayerInterface* player;
    int type = 0; // 根据用户选择类型
    player = CreatePlayer::createPlayer(type);
    player->play();
    player->stop();
    delete player;
    return 0;
}

注意:工厂类不负责释放对象内存(因工厂仅提供静态创建方法,无实例生命周期关联),内存释放由调用者负责。

改进

原始指针需手动管理内存,可借助 RAII 机制用智能指针优化:

#include <memory>

class CreatePlayer {
public:
    static std::unique_ptr<PlayerInterface> createPlayer(int playerType) {
        switch (playerType) {
            case 0:
                return std::make_unique<FfmpegPlayer>();
            case 1:
                return std::make_unique<GstreamerPlayer>();
            default:
                return nullptr;
        }
    }
};

// 用法  
int main() {
    std::unique_ptr<PlayerInterface> player;
    int type = 0;
    player = CreatePlayer::createPlayer(type);
    player->play();
    player->stop();
    return 0;
}

工厂模式(工厂方法模式)

动机

简单工厂模式的痛点:若新增播放框架(如 DirectShow),需继承抽象产品类并在工厂类中新增 case 分支。但作为库设计,这违反 开闭原则(对扩展开放,对修改关闭)。
解决思路:将工厂类也进行抽象——这就是工厂模式的核心。

定义

工厂模式与简单工厂模式的区别在于 抽象了工厂类。扩展时只需继承工厂抽象类和产品抽象类,无需修改原有代码。工厂模式有4种角色:

  • 抽象工厂角色(Creator),所有具体工厂都要实现这个接口;
  • 具体工厂(Concrete Creator),负责实例化具体产品对象;
  • 抽象角色(Product),和简单工厂模式一样,它是工厂类所创建的所有实例的类的共同基类,用于描述产品的公共接口。
  • 具体产品角色(Concrete Product),具体工厂类所要实例化的对象。

示例

先抽象工厂类(移除 static,因与 virtual 冲突):

class CreatorInterface {
public:
    virtual PlayerInterface* create() = 0;
};

具体工厂类:

class FfmpegCreator : public CreatorInterface {
public:
    PlayerInterface* create() override {
        return new FfmpegPlayer();
    }
};

class GstreamerCreator : public CreatorInterface {
public:
    PlayerInterface* create() override {
        return new GstreamerPlayer();
    }
};

使用示例:

int main() {
    CreatorInterface* creator;
    PlayerInterface* player;
    int type = 1; // 选择工厂类型  
    if (type == 0) {
        creator = new FfmpegCreator();
    } else {
        creator = new GstreamerCreator();
    }
    player = creator->create();
    player->play();
    player->stop();
    delete player;
    delete creator;
    return 0;
}

新增 DirectShow 支持时,仅需:

  1. 实现具体产品类:
class DirectShowPlayer : public PlayerInterface {
public:
    void play() override {
        std::cout << "DirectShow play" << std::endl;
    }
    void stop() override {
        std::cout << "DirectShow stop" << std::endl;
    }
};
  1. 实现具体工厂类:
class DirectShowCreator : public CreatorInterface {
public:
    PlayerInterface* create() override {
        return new DirectShowPlayer();
    }
};

使用时直接创建新工厂:

CreatorInterface* creator = new DirectShowCreator();
PlayerInterface* player = creator->create();
// ...

改进

用智能指针优化内存管理(新增虚析构函数确保正确释放):

#include <memory>
#include <iostream>

class PlayerInterface {
public:
    virtual void play() = 0;
    virtual void stop() = 0;
    virtual ~PlayerInterface() = default; // 新增虚析构
};

// 具体产品类(同上,略)

class CreatorInterface {
public:
    virtual ~CreatorInterface() {
        std::cout << "~CreatorInterface" << std::endl;
    }
    virtual std::unique_ptr<PlayerInterface> create() = 0;
};

class FfmpegCreator : public CreatorInterface {
public:
    ~FfmpegCreator() override {
        std::cout << "~FfmpegCreator" << std::endl;
    }
    std::unique_ptr<PlayerInterface> create() override {
        return std::make_unique<FfmpegPlayer>();
    }
};

// 其他具体工厂类(同上,略)

int main() {
    std::unique_ptr<CreatorInterface> creator = std::make_unique<FfmpegCreator>();
    std::unique_ptr<PlayerInterface> player = creator->create();
    player->play();
    player->stop();
    return 0;
}
posted @ 2025-06-11 15:14  thammer  阅读(18)  评论(0)    收藏  举报