工厂模式是创建型设计模式中最常用的一种,核心思想是将对象的创建和使用分离。
与其在代码中到处 new 对象,不如由一个专门的"工厂"来负责。这样做最大的好处是:当需要更换或新增一个类型时,你只需要修改工厂,而不用改动所有调用它的业务代码。
工厂模式主要分三种:简单工厂、工厂方法和抽象工厂,复杂度依次递增。
一、简单工厂
这是最基础的形式,严格来说不算一种设计模式,而是一种编程习惯。由一个工厂类根据传入的参数,决定创建哪种产品。
适用场景:产品种类少,调用者只需传参就能获得对象,不想关心创建细节。
cpp
#include <iostream>
#include <memory>
#include <string>
// 1. 抽象产品
class Car {
public:
virtual void run() = 0;
virtual ~Car() = default;
};
// 2. 具体产品
class Bmw : public Car {
public:
void run() override { std::cout << "宝马在飞驰" << std::endl; }
};
class Audi : public Car {
public:
void run() override { std::cout << "奥迪在狂奔" << std::endl; }
};
// 3. 简单工厂
class SimpleCarFactory {
public:
static std::unique_ptr<Car> createCar(const std::string& type) {
if (type == "bmw") return std::make_unique<Bmw>();
if (type == "audi") return std::make_unique<Audi>();
return nullptr;
}
};
int main() {
auto car = SimpleCarFactory::createCar("bmw");
if (car) car->run(); // 输出:宝马在飞驰
}
缺点:要新增车型,必须修改 SimpleCarFactory 的 if-else,违反了开闭原则(对扩展开放,对修改关闭)。
二、工厂方法
为了解决简单工厂违背开闭原则的问题,把工厂也抽象化。每个具体产品对应一个具体工厂,新增产品时,只需新增工厂类,不用修改原有代码。
适用场景:产品类型会不断扩展,调用者明确地需要一个特定类型的对象。
cpp
#include <iostream>
#include <memory>
// 1. 抽象产品
class Car {
public:
virtual void run() = 0;
virtual ~Car() = default;
};
// 2. 具体产品
class Bmw : public Car {
public:
void run() override { std::cout << "宝马在飞驰" << std::endl; }
};
class Audi : public Car {
public:
void run() override { std::cout << "奥迪在狂奔" << std::endl; }
};
// 3. 抽象工厂
class CarFactory {
public:
virtual std::unique_ptr<Car> createCar() = 0;
virtual ~CarFactory() = default;
};
// 4. 具体工厂
class BmwFactory : public CarFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<Bmw>();
}
};
class AudiFactory : public CarFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<Audi>();
}
};
int main() {
// 想造宝马,就注入宝马工厂
std::unique_ptr<CarFactory> factory = std::make_unique<BmwFactory>();
auto car = factory->createCar();
car->run(); // 输出:宝马在飞驰
// 新增奔驰,只需新增 Benz 和 BenzFactory,不碰现有代码
}
这样,系统对扩展开放,对修改关闭。
三、抽象工厂
当产品不再只有一个,而是一个产品族(比如不仅有汽车,还有配套的轮胎、引擎),且需要保证同一族的产品能一起使用时,就用抽象工厂。
适用场景:需要创建一系列相互依赖或关联的对象,并要保证它们之间的兼容性。
cpp
#include <iostream>
#include <memory>
// --- 抽象产品 ---
class Car {
public:
virtual void run() = 0;
virtual ~Car() = default;
};
class Tire {
public:
virtual void roll() = 0;
virtual ~Tire() = default;
};
// --- 宝马族产品 ---
class BmwCar : public Car {
public:
void run() override { std::cout << "宝马跑车启动" << std::endl; }
};
class BmwTire : public Tire {
public:
void roll() override { std::cout << "宝马专用轮胎滚动" << std::endl; }
};
// --- 奥迪族产品 ---
class AudiCar : public Car {
public:
void run() override { std::cout << "奥迪轿车启动" << std::endl; }
};
class AudiTire : public Tire {
public:
void roll() override { std::cout << "奥迪专用轮胎滚动" << std::endl; }
};
// --- 抽象工厂:能创建一整个产品族 ---
class AbstractFactory {
public:
virtual std::unique_ptr<Car> createCar() = 0;
virtual std::unique_ptr<Tire> createTire() = 0;
virtual ~AbstractFactory() = default;
};
// --- 具体工厂:宝马工厂生产宝马的全套产品 ---
class BmwFactory : public AbstractFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<BmwCar>();
}
std::unique_ptr<Tire> createTire() override {
return std::make_unique<BmwTire>();
}
};
// --- 具体工厂:奥迪工厂生产奥迪的全套产品 ---
class AudiFactory : public AbstractFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<AudiCar>();
}
std::unique_ptr<Tire> createTire() override {
return std::make_unique<AudiTire>();
}
};
int main() {
// 换一个工厂,就能把整组产品换掉,绝不会把宝马轮胎装到奥迪上
std::unique_ptr<AbstractFactory> factory = std::make_unique<BmwFactory>();
auto car = factory->createCar();
auto tire = factory->createTire();
car->run();
tire->roll();
}
抽象工厂的关键:保证"宝马工厂只出宝马配件",从而保证产品族内的一致性。
总结与选择建议
模式 核心思想 何时使用
简单工厂 一个工厂根据参数创建不同产品 对象种类少,不想为每个类建工厂,简单够用
工厂方法 每个产品对应一个工厂,工厂也抽象化 产品会不断扩展,需要符合开闭原则
抽象工厂 创建一组相关或依赖的对象(产品族) 系统需要由多个关联组件构成,并要切换整套产品系列(如换皮肤、跨平台UI组件)
最终建议:别一开始就上最复杂的设计。先用简单工厂解决眼前问题,当发现 if-else 膨胀或需要频繁新增产品时,再平滑地重构为工厂方法或抽象工厂。