1.c++设计模式-工厂模式

工厂模式是创建型设计模式中最常用的一种,核心思想是将对象的创建和使用分离。

与其在代码中到处 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 膨胀或需要频繁新增产品时,再平滑地重构为工厂方法或抽象工厂。

相关推荐
汉克老师2 小时前
GESP2025年3月认证C++五级( 第三部分编程题(2、原根判断))
c++·算法·模运算·gesp5级·gesp五级·原根·分解质因数
winner88812 小时前
从零吃透C++命名空间、std、#include、string、vector
java·开发语言·c++
AI进化营-智能译站2 小时前
ROS2 C++开发系列07-高效构建机器人决策逻辑,运算符与控制流实战
开发语言·c++·ai·机器人
winner88812 小时前
C++ 命名空间、虚函数、抽象类、protected 权限全套通俗易懂精讲(附与 Java 对比)
java·开发语言·c++
不会编程的懒洋洋3 小时前
C# P/Invoke 基础
开发语言·c++·笔记·安全·机器学习·c#·p/invoke
24白菜头3 小时前
【无标题】
c++·笔记·学习·harmonyos
charlie1145141913 小时前
嵌入式C++实践开发第21篇(单片机实践):按钮输入 —— 硬件原理、消抖与HAL API
开发语言·c++·单片机
AKDreamer_HeXY3 小时前
QOJ 12255 - 36 Puzzle 题解
数据结构·c++·数学·算法·icpc·qoj
AI进化营-智能译站4 小时前
ROS2 C++开发系列13-运算符重载让ROS2消息处理更自然
java·开发语言·c++·ai