设计模式-创建型模式之-工厂模式
简单工厂模式
动机
在实际开发中,我曾遇到这样的需求:实现一个播放器,要求支持播放列表设置、播放、停止、暂停、跳转等操作。正常情况下直接实现播放器类即可,但需求要求支持不同多媒体库(如 FFmpeg 或 GStreamer)。若分别实现两种播放器类,业务逻辑中每次操作播放器时都需判断类型;若扩展到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 支持时,仅需:
- 实现具体产品类:
class DirectShowPlayer : public PlayerInterface {
public:
void play() override {
std::cout << "DirectShow play" << std::endl;
}
void stop() override {
std::cout << "DirectShow stop" << std::endl;
}
};
- 实现具体工厂类:
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;
}

浙公网安备 33010602011771号