【设计模式】C++ 工厂模式的理解

工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。

核心思想

将对象的创建与使用分离,客户端不需要知道具体创建哪个类的实例,只需要通过工厂接口获取所需对象。

主要类型

1. 简单工厂模式(Simple Factory)

  • 一个工厂类根据传入的参数创建不同的对象

  • 不符合开闭原则(新增产品需要修改工厂类)

java
// 产品接口
interface Product {
    void operation();
}

// 具体产品
class ConcreteProductA implements Product {
    public void operation() {
        System.out.println("Product A");
    }
}

class ConcreteProductB implements Product {
    public void operation() {
        System.out.println("Product B");
    }
}

// 简单工厂
class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        return null;
    }
}

2. 工厂方法模式(Factory Method)

  • 定义一个创建对象的接口,让子类决定实例化哪个类

  • 符合开闭原则

java
// 工厂接口
interface Factory {
    Product createProduct();
}

// 具体工厂
class FactoryA implements Factory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

class FactoryB implements Factory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

3. 抽象工厂模式(Abstract Factory)

  • 创建相关或依赖对象的家族,而不需要指定具体类

  • 适合创建一系列相关产品

java
// 抽象工厂
interface AbstractFactory {
    Product createProduct();
    AnotherProduct createAnotherProduct();
}

// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
    public Product createProduct() {
        return new ProductA();
    }
    public AnotherProduct createAnotherProduct() {
        return new AnotherProductA();
    }
}

优点

  1. 解耦:客户端与具体产品类分离

  2. 可扩展:新增产品类型时无需修改现有代码(工厂方法模式)

  3. 单一职责:将创建逻辑集中管理

  4. 易于维护:对象创建代码集中管理

缺点

  1. 增加复杂度:需要引入多个类和接口

  2. 理解成本:对新手可能较难理解

应用场景

  • 当一个类不知道它所需要的对象类时

  • 当一个类希望由其子类来指定创建的对象时

  • 当需要将对象的创建与使用分离时

  • 系统需要支持多种产品类型时

现实例子

java
// JDK 中的 Calendar.getInstance()
Calendar cal = Calendar.getInstance();
// 根据本地化设置返回不同的 Calendar 子类实例

// Spring 中的 BeanFactory
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
Object bean = context.getBean("beanName");

工厂模式是面向对象设计中非常重要的模式,它体现了"针对接口编程,而不是针对实现编程"的原则。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
举一个易懂的,基于C++的程序
 
 
 
 
 
 

我来用一个汽车制造工厂的例子,用 C++ 实现工厂模式。这个例子非常直观易懂!

场景描述

假设我们有一个汽车工厂,能生产不同类型的汽车(轿车、SUV、卡车)。

1. 简单工厂模式示例

cpp
#include <iostream>
#include <string>
using namespace std;

// 1. 抽象产品类 - 汽车
class Car {
public:
    virtual void drive() = 0;
    virtual ~Car() {}
};

// 2. 具体产品类
class Sedan : public Car {
public:
    void drive() override {
        cout << "驾驶轿车:平稳舒适" << endl;
    }
};

class SUV : public Car {
public:
    void drive() override {
        cout << "驾驶SUV:越野能力强" << endl;
    }
};

class Truck : public Car {
public:
    void drive() override {
        cout << "驾驶卡车:载货量大" << endl;
    }
};

// 3. 简单工厂
class CarFactory {
public:
    static Car* createCar(const string& type) {
        if (type == "sedan") {
            return new Sedan();
        } else if (type == "suv") {
            return new SUV();
        } else if (type == "truck") {
            return new Truck();
        }
        return nullptr;
    }
};

// 4. 客户端使用
int main() {
    // 客户只需要告诉工厂要什么类型的车,不需要知道具体怎么创建
    Car* myCar1 = CarFactory::createCar("sedan");
    Car* myCar2 = CarFactory::createCar("suv");
    Car* myCar3 = CarFactory::createCar("truck");
    
    if (myCar1) myCar1->drive();  // 驾驶轿车:平稳舒适
    if (myCar2) myCar2->drive();  // 驾驶SUV:越野能力强
    if (myCar3) myCar3->drive();  // 驾驶卡车:载货量大
    
    // 清理内存
    delete myCar1;
    delete myCar2;
    delete myCar3;
    
    return 0;
}

2. 工厂方法模式示例(更灵活)

cpp
#include <iostream>
#include <memory>
using namespace std;

// 抽象产品
class Car {
public:
    virtual void drive() = 0;
    virtual ~Car() {}
};

// 具体产品
class Benz : public Car {
public:
    void drive() override {
        cout << "驾驶奔驰:豪华舒适" << endl;
    }
};

class BMW : public Car {
public:
    void drive() override {
        cout << "驾驶宝马:运动操控" << endl;
    }
};

// 抽象工厂
class CarFactory {
public:
    virtual unique_ptr<Car> produceCar() = 0;
    virtual ~CarFactory() {}
};

// 具体工厂
class BenzFactory : public CarFactory {
public:
    unique_ptr<Car> produceCar() override {
        return make_unique<Benz>();
    }
};

class BMWFactory : public CarFactory {
public:
    unique_ptr<Car> produceCar() override {
        return make_unique<BMW>();
    }
};

// 客户端
int main() {
    // 创建奔驰工厂
    unique_ptr<CarFactory> benzFactory = make_unique<BenzFactory>();
    unique_ptr<Car> benz = benzFactory->produceCar();
    benz->drive();  // 驾驶奔驰:豪华舒适
    
    // 创建宝马工厂
    unique_ptr<CarFactory> bmwFactory = make_unique<BMWFactory>();
    unique_ptr<Car> bmw = bmwFactory->produceCar();
    bmw->drive();   // 驾驶宝马:运动操控
    
    return 0;
}

3. 更实际的例子:图形绘制

cpp
#include <iostream>
#include <vector>
using namespace std;

// 图形基类
class Shape {
public:
    virtual void draw() = 0;
    virtual ~Shape() {}
};

// 具体图形
class Circle : public Shape {
public:
    void draw() override {
        cout << "绘制圆形 ○" << endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() override {
        cout << "绘制矩形 ▭" << endl;
    }
};

class Triangle : public Shape {
public:
    void draw() override {
        cout << "绘制三角形 △" << endl;
    }
};

// 图形工厂
class ShapeFactory {
public:
    static Shape* createShape(const string& type) {
        if (type == "circle") {
            return new Circle();
        } else if (type == "rectangle") {
            return new Rectangle();
        } else if (type == "triangle") {
            return new Triangle();
        }
        return nullptr;
    }
};

int main() {
    // 用户输入想要创建的图形
    vector<string> requests = {"circle", "rectangle", "triangle"};
    
    cout << "开始绘制图形:" << endl;
    for (const auto& request : requests) {
        Shape* shape = ShapeFactory::createShape(request);
        if (shape) {
            shape->draw();
            delete shape;  // 记得释放内存
        }
    }
    
    return 0;
}

关键理解点

为什么用工厂模式?

假设没有工厂模式:

cpp
// 客户端需要知道所有具体类
Car* car;
if (userChoice == "sedan") {
    car = new Sedan();
} else if (userChoice == "suv") {
    car = new SUV();
} else if (userChoice == "truck") {
    car = new Truck();
}
// 每次新增车型都要修改这里

有了工厂模式:

cpp
// 客户端代码很简单,与具体类解耦
Car* car = CarFactory::createCar(userChoice);
// 新增车型只需要修改工厂类,客户端代码不变

输出结果

text
开始绘制图形:
绘制圆形 ○
绘制矩形 ▭
绘制三角形 △

总结

工厂模式就像现实生活中的餐馆

  • 顾客(客户端):只需要点菜("我要一个披萨")

  • 服务员(工厂):接收订单,告诉厨房做什么

  • 厨房(具体工厂):根据订单制作具体的披萨(芝士披萨、海鲜披萨等)

  • 顾客最终得到披萨,但不需要知道披萨的具体制作过程

这种模式让代码更灵活、可维护、易扩展

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
我想问上面例子中的简单工厂,为什么是 static Car * 类型,而不用智能指针呢?另外,我对工厂模式的理解是:对于一个需求有好几种实现方式,每种方式都是一个类,然后工厂模式可以把这些不同的类,抽象成一个类,供最上层调用
 
 
 
 
 
 

你的理解基本正确,但让我先回答第一个问题,然后补充一下你的理解。

1. 为什么用 static Car* 而不用智能指针?

你观察得很仔细!用原始指针确实不是最佳实践。现代C++应该使用智能指针。让我展示更好的实现

cpp
#include <iostream>
#include <memory>
using namespace std;

// 产品类
class Car {
public:
    virtual void drive() = 0;
    virtual ~Car() = default;
};

class Sedan : public Car {
public:
    void drive() override {
        cout << "驾驶轿车" << endl;
    }
};

// 使用智能指针的工厂
class CarFactory {
public:
    static unique_ptr<Car> createCar(const string& type) {
        if (type == "sedan") {
            return make_unique<Sedan>();
        } else if (type == "suv") {
            return make_unique<SUV>();  // 假设有SUV类
        }
        return nullptr;
    }
};

// 客户端使用
int main() {
    // 使用智能指针,无需手动delete
    auto myCar = CarFactory::createCar("sedan");
    if (myCar) {
        myCar->drive();
    }
    // myCar会自动释放内存
    return 0;
}

为什么很多教程用原始指针?

  1. 历史原因:老教程或教材

  2. 简洁性:为了专注于模式本身

  3. 跨语言兼容:让Java/C#程序员容易理解

2. 你对工厂模式的理解(补充说明)

你的理解方向是对的,但让我更精确地描述一下:

cpp
// 你的理解:"对于一个需求有好几种实现方式"
// 确实如此!比如"驾驶汽车"这个需求

// 1. 首先定义抽象接口(需求规范)
class Car {
public:
    virtual void drive() = 0;  // 驾驶需求
    virtual void fuel() = 0;   // 加油需求
    virtual ~Car() {}
};

// 2. "每种方式都是一个类"(多种实现)
class ElectricCar : public Car {  // 方式1:电动汽车
public:
    void drive() override { cout << "电力驱动" << endl; }
    void fuel() override { cout << "充电" << endl; }
};

class GasolineCar : public Car {  // 方式2:汽油车
public:
    void drive() override { cout << "汽油驱动" << endl; }
    void fuel() override { cout << "加油" << endl; }
};

class HybridCar : public Car {    // 方式3:混合动力
public:
    void drive() override { cout << "混合驱动" << endl; }
    void fuel() override { cout << "加油或充电" << endl; }
};

// 3. "工厂把这些类抽象成一个类,供上层调用"
class CarFactory {
public:
    // 工厂方法:根据参数创建具体对象
    static unique_ptr<Car> createCar(const string& type) {
        if (type == "electric") {
            return make_unique<ElectricCar>();
        } else if (type == "gasoline") {
            return make_unique<GasolineCar>();
        } else if (type == "hybrid") {
            return make_unique<HybridCar>();
        }
        return nullptr;
    }
};

// 4. "最上层调用"(客户端代码)
class Client {
public:
    void useCar() {
        // 客户端只需要知道抽象类型Car,不知道具体实现
        unique_ptr<Car> myCar = CarFactory::createCar("electric");
        
        // 统一接口调用
        myCar->drive();  // 可能是电力驱动
        myCar->fuel();   // 可能是充电
        
        // 换个类型试试
        myCar = CarFactory::createCar("gasoline");
        myCar->drive();  // 现在是汽油驱动
        myCar->fuel();   // 现在是加油
    }
};

3. 更生动的现实比喻

想象一个外卖平台

cpp
// 抽象:食物
class Food {
public:
    virtual void prepare() = 0;
    virtual void deliver() = 0;
};

// 具体食物
class Pizza : public Food {
    void prepare() override { cout << "制作披萨" << endl; }
    void deliver() override { cout << "配送披萨" << endl; }
};

class Burger : public Food {
    void prepare() override { cout << "制作汉堡" << endl; }
    void deliver() override { cout << "配送汉堡" << endl; }
};

// 用户(客户端)
class Customer {
public:
    void orderFood(const string& foodType) {
        // 用户只调用FoodFactory,不知道具体餐厅
        unique_ptr<Food> food = FoodFactory::order(foodType);
        food->prepare();
        food->deliver();
    }
};

// 外卖平台(工厂)
class FoodFactory {
public:
    static unique_ptr<Food> order(const string& type) {
        if (type == "pizza") {
            return make_unique<Pizza>();  // 可能调用披萨店
        } else if (type == "burger") {
            return make_unique<Burger>(); // 可能调用汉堡店
        }
        return nullptr;
    }
};

4. 关键优势总结

工厂模式的核心价值

cpp
// 没有工厂模式:客户端需要知道所有具体类
void badExample() {
    string choice = getUserChoice();
    
    if (choice == "electric") {
        ElectricCar car;
        car.drive();
    } else if (choice == "gasoline") {
        GasolineCar car;
        car.drive();
    } else if (choice == "hybrid") {
        HybridCar car;
        car.drive();
    }
    // 新增类型时,需要修改这里!
}

// 使用工厂模式:客户端只依赖抽象
void goodExample() {
    string choice = getUserChoice();
    
    // 创建逻辑封装在工厂中
    unique_ptr<Car> car = CarFactory::createCar(choice);
    car->drive();  // 多态调用
    
    // 新增类型时,只需修改工厂,这里不变!
}

总结

你的理解正确,工厂模式就是:

  1. 抽象共性:多个具体类实现同一个接口

  2. 封装创建:把对象创建的复杂度隐藏起来

  3. 解耦调用:客户端只依赖抽象,不依赖具体类

简单说:工厂就像是一个"黑盒子",你告诉它你要什么(参数),它就给你相应的对象。你不需要知道对象是怎么被创建出来的,也不需要知道具体的实现类是谁。

这种设计让代码:

  • ✅ 更易维护:创建逻辑集中管理

  • ✅ 更易扩展:新增类型不影响现有代码

  • ✅ 更灵活:可以动态切换实现

  • ✅ 更安全:使用智能指针避免内存泄漏

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
我有一个疑问:既然使用了抽象类,那么直接用抽象类初始化就行了,为啥还要弄出来一个工厂类
 
 
 
 
 
 

这是一个很好的问题!很多人刚开始学工厂模式时都有这个疑问。让我用一个具体的例子来解释为什么需要工厂类。

直接使用抽象类的问题

cpp
// 假设有这些类
class Animal {
public:
    virtual void speak() = 0;
};

class Dog : public Animal {
public:
    void speak() override { cout << "汪汪!" << endl; }
};

class Cat : public Animal {
public:
    void speak() override { cout << "喵喵!" << endl; }
};

// 客户端代码
int main() {
    // 错误!不能直接实例化抽象类
    // Animal animal;  // 编译错误
    
    // 必须知道具体类
    Animal* pet1 = new Dog();  // 客户端依赖Dog类
    Animal* pet2 = new Cat();  // 客户端依赖Cat类
    
    pet1->speak();
    pet2->speak();
    
    delete pet1;
    delete pet2;
    return 0;
}

问题所在

1. 客户端代码与具体类耦合

cpp
// 问题:客户端需要知道所有具体类
void createPet(const string& type) {
    Animal* pet = nullptr;
    
    if (type == "dog") {
        pet = new Dog();  // 直接依赖Dog类
    } else if (type == "cat") {
        pet = new Cat();  // 直接依赖Cat类
    } else if (type == "bird") {
        pet = new Bird(); // 新增类型时,要修改这里!
    }
    
    // 使用pet...
}

每新增一个动物类型,都要修改客户端代码!

2. 对象创建逻辑分散

cpp
// 多个地方都需要创建动物
class PetShop {
    Animal* buyPet(const string& type) {
        if (type == "dog") return new Dog();
        if (type == "cat") return new Cat();
        return nullptr;
    }
};

class Zoo {
    Animal* getAnimal(const string& type) {
        if (type == "dog") return new Dog();
        if (type == "cat") return new Cat();  // 重复的创建逻辑!
        return nullptr;
    }
};

// 创建逻辑重复了!修改时要在多个地方改

解决方案:使用工厂类

cpp
// 动物工厂
class AnimalFactory {
public:
    static unique_ptr<Animal> createAnimal(const string& type) {
        if (type == "dog") {
            return make_unique<Dog>();
        } else if (type == "cat") {
            return make_unique<Cat>();
        } else if (type == "bird") {
            return make_unique<Bird>();
        }
        return nullptr;
    }
};

// 客户端代码
int main() {
    // 客户端只依赖抽象类和工厂,不依赖具体类
    vector<string> petTypes = {"dog", "cat", "bird"};
    
    for (const auto& type : petTypes) {
        auto pet = AnimalFactory::createAnimal(type);
        pet->speak();  // 多态调用
    }
    
    return 0;
}

工厂类的核心价值

1. 封装变化点

cpp
// 假设创建逻辑很复杂
class AnimalFactory {
public:
    static unique_ptr<Animal> createAnimal(const string& type) {
        // 复杂的创建逻辑都封装在这里
        if (type == "dog") {
            // 可能需要:读取配置、初始化数据、注册到管理器等
            auto dog = make_unique<Dog>();
            dog->setAge(calculateDogAge());
            dog->registerToKennel();
            return dog;
        }
        else if (type == "cat") {
            // 猫的创建逻辑可能完全不同
            auto cat = make_unique<Cat>();
            cat->setColor(readConfig("cat_color"));
            cat->vaccinate();
            return cat;
        }
        // ... 其他复杂逻辑
    }
};

// 客户端完全不知道这些复杂性
auto pet = AnimalFactory::createAnimal("dog");
// 客户端拿到的是完全初始化好的对象

2. 统一管理创建逻辑

cpp
// 没有工厂:每个使用的地方都要写创建逻辑
void function1() {
    if (condition) {
        Animal* a = new Dog();
    } else {
        Animal* a = new Cat();
    }
}

void function2() {
    if (condition) {
        Animal* a = new Dog();  // 重复代码!
    } else {
        Animal* a = new Cat();
    }
}

// 有工厂:创建逻辑统一管理
void function1() {
    auto animal = AnimalFactory::createAnimal(getType());
}

void function2() {
    auto animal = AnimalFactory::createAnimal(getType());
}

3. 便于扩展和维护

cpp
// 初始版本
class AnimalFactory {
public:
    static Animal* createAnimal(const string& type) {
        if (type == "dog") return new Dog();
        if (type == "cat") return new Cat();
        return nullptr;
    }
};

// 版本2:添加缓存
class AnimalFactory {
private:
    static unordered_map<string, Animal*> cache;
    
public:
    static Animal* createAnimal(const string& type) {
        // 检查缓存
        if (cache.find(type) != cache.end()) {
            return cache[type]->clone();  // 原型模式
        }
        
        // 创建新对象
        Animal* animal = nullptr;
        if (type == "dog") animal = new Dog();
        else if (type == "cat") animal = new Cat();
        
        // 加入缓存
        if (animal) cache[type] = animal;
        return animal ? animal->clone() : nullptr;
    }
};

// 版本3:从配置文件读取
class AnimalFactory {
public:
    static Animal* createAnimal(const string& type) {
        // 从XML/JSON配置文件读取创建参数
        Config config = loadConfig("animals.xml");
        string className = config.getClassName(type);
        
        // 使用反射动态创建
        return Reflection::createInstance(className);
    }
};

// 客户端代码完全不需要修改!
// auto pet = AnimalFactory::createAnimal("dog");

一个更实际的例子

cpp
// 数据库连接示例
class DatabaseConnection {
public:
    virtual void connect() = 0;
    virtual void query(const string& sql) = 0;
};

class MySQLConnection : public DatabaseConnection {
public:
    void connect() override { cout << "连接MySQL" << endl; }
    void query(const string& sql) override { cout << "执行MySQL查询: " << sql << endl; }
};

class PostgreSQLConnection : public DatabaseConnection {
public:
    void connect() override { cout << "连接PostgreSQL" << endl; }
    void query(const string& sql) override { cout << "执行PostgreSQL查询: " << sql << endl; }
};

// 为什么需要工厂?
class DatabaseFactory {
public:
    static unique_ptr<DatabaseConnection> createConnection(const string& dbType) {
        // 这里可能有复杂的逻辑:
        // 1. 读取配置文件
        // 2. 设置连接参数
        // 3. 初始化连接池
        // 4. 验证权限
        // 5. 记录日志等
        
        if (dbType == "mysql") {
            auto conn = make_unique<MySQLConnection>();
            // 初始化MySQL特定参数
            conn->setCharset("utf8mb4");
            conn->setTimeout(30);
            return conn;
        } else if (dbType == "postgresql") {
            auto conn = make_unique<PostgreSQLConnection>();
            // 初始化PostgreSQL特定参数
            conn->setSchema("public");
            return conn;
        }
        return nullptr;
    }
};

// 客户端使用
class Application {
public:
    void run() {
        // 简单的一行代码,背后是复杂的创建逻辑
        auto db = DatabaseFactory::createConnection("mysql");
        db->connect();
        db->query("SELECT * FROM users");
    }
};

总结

为什么需要工厂类:

  1. 解耦:客户端不依赖具体类,只依赖抽象

  2. 封装:把复杂的创建逻辑封装起来

  3. 集中管理:创建逻辑在同一个地方,便于维护

  4. 可扩展:新增类型时,只需修改工厂,不影响客户端

  5. 可配置:可以通过配置文件等动态决定创建什么对象

简单比喻

  • 没有工厂:你要吃披萨,得自己去买面粉、奶酪、烤箱,自己烤

  • 有工厂:你打电话给披萨店说"我要一个披萨",店里准备好一切送给你

工厂类就是那个"披萨店",帮你处理所有复杂的创建过程!

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
可不可以这样这里,所谓的工厂,就是增强了抽象类的用法
 
 
 
 
 
 

你的理解非常准确! 工厂模式本质上就是 "增强版"的抽象类用法。让我用你的这个思路来重新解释。

工厂 = 抽象类用法的增强

1. 基础抽象类用法(不够强)

cpp
// 1. 定义抽象接口
class Animal {
public:
    virtual void speak() = 0;
    virtual ~Animal() {}
};

// 2. 具体实现
class Dog : public Animal {
public:
    void speak() override { cout << "汪汪" << endl; }
};

class Cat : public Animal {
public:
    void speak() override { cout << "喵喵" << endl; }
};

// 3. 客户端直接使用(问题所在)
void clientCode() {
    // 客户端需要知道具体类名
    Animal* pet = new Dog();  // 直接依赖Dog类
    
    // 如果要换类型,必须修改代码
    // Animal* pet = new Cat();  // 需要手动改
    
    pet->speak();
    delete pet;
}

问题:抽象类解决了"怎么用",但没解决"怎么创建"。

2. 增强版:工厂模式

cpp
// 增强点1:封装创建逻辑
class AnimalCreator {
public:
    // 动态决定创建哪个具体类
    static Animal* createAnimal(const string& type) {
        if (type == "dog") return new Dog();
        if (type == "cat") return new Cat();
        return nullptr;
    }
};

// 客户端使用增强版
void enhancedClientCode() {
    // 运行时决定创建什么
    string userChoice = "dog";  // 可以从配置文件、用户输入等获取
    
    // 不依赖具体类名!
    Animal* pet = AnimalCreator::createAnimal(userChoice);
    pet->speak();
    
    // 想换类型?只需改配置/输入,代码不变
    userChoice = "cat";
    Animal* anotherPet = AnimalCreator::createAnimal(userChoice);
    anotherPet->speak();
}

工厂模式增强了什么?

增强1:创建过程的抽象化

cpp
// 没有工厂:创建与使用混合
void process1() {
    Animal* a = new Dog();  // 创建
    a->speak();             // 使用
    delete a;
}

void process2() {
    Animal* a = new Dog();  // 重复创建逻辑
    a->run();
    delete a;
}

// 有工厂:创建逻辑抽象化
void process1() {
    Animal* a = AnimalFactory::create("dog");  // 抽象化创建
    a->speak();
    delete a;
}

void process2() {
    Animal* a = AnimalFactory::create("dog");  // 复用创建逻辑
    a->run();
    delete a;
}

增强2:条件创建的封装

cpp
// 复杂的选择逻辑被封装
class SmartAnimalFactory {
public:
    static Animal* createOptimalAnimal() {
        // 这个逻辑可能很复杂,但客户端不需要知道
        
        // 根据系统资源决定
        if (hasLowMemory()) {
            return new SmallDog();  // 内存占用小的狗
        }
        
        // 根据用户偏好决定
        if (userLikesCats()) {
            return new PersianCat();  // 波斯猫
        }
        
        // 根据时间决定
        if (isNightTime()) {
            return new Owl();  // 夜行动物
        }
        
        // 默认
        return new GenericDog();
    }
};

// 客户端很简单
auto pet = SmartAnimalFactory::createOptimalAnimal();
// 不知道背后复杂的决策逻辑

增强3:创建过程的扩展点

cpp
// 可以添加各种"钩子"和扩展
class ConfigurableFactory {
public:
    static Animal* createWithConfig(const string& type) {
        // 1. 记录日志
        log("开始创建动物: " + type);
        
        // 2. 验证权限
        if (!hasPermission(type)) {
            throw PermissionException();
        }
        
        // 3. 创建对象
        Animal* animal = nullptr;
        if (type == "dog") animal = new Dog();
        else if (type == "cat") animal = new Cat();
        
        // 4. 后处理
        if (animal) {
            animal->initializeFromConfig();
            registerToTracker(animal);
        }
        
        // 5. 更多处理...
        return animal;
    }
};

用你的话来理解

抽象类本身

cpp
// 抽象类解决了"接口统一"问题
// 告诉客户端:"所有动物都有speak()方法"
class Animal {
    virtual void speak() = 0;  // 接口规范
};

// 客户端知道怎么用
animal->speak();  // 多态调用

工厂增强

cpp
// 工厂解决了"实例化统一"问题  
// 告诉客户端:"所有动物都通过我来创建"
class AnimalFactory {
    static Animal* create(string type);  // 创建规范
};

// 客户端知道怎么创建
Animal* animal = AnimalFactory::create("dog");
// 不用关心是new Dog()还是new Cat()

一个完整对比

cpp
// ================ 方案1:只用抽象类 ================
// 问题:创建逻辑分散在各处
class Game {
    Character* createHero() {
        // 需要知道所有具体类
        if (weapon == "sword") return new Warrior();
        if (weapon == "bow") return new Archer();
        if (weapon == "staff") return new Mage();
        return nullptr;
    }
    
    Character* createEnemy() {
        // 重复的创建逻辑
        if (type == "orc") return new Orc();
        if (type == "goblin") return new Goblin();
        return nullptr;
    }
};

// ================ 方案2:抽象类+工厂(增强版) ================
class CharacterFactory {
    static Character* create(string type) {
        // 集中管理所有创建逻辑
        if (type == "warrior" || type == "sword") return new Warrior();
        if (type == "archer" || type == "bow") return new Archer();
        if (type == "mage" || type == "staff") return new Mage();
        if (type == "orc") return new Orc();
        if (type == "goblin") return new Goblin();
        return nullptr;
    }
};

class Game {
    Character* createHero() {
        // 统一接口创建
        return CharacterFactory::create(weapon);
    }
    
    Character* createEnemy() {
        return CharacterFactory::create(enemyType);
    }
};

总结

你的理解完全正确

  • 抽象类解决了"如何统一使用"的问题(接口抽象)

  • 工厂模式解决了"如何统一创建"的问题(创建抽象)

工厂模式 = 抽象类用法 + 创建逻辑的封装

就像:

  • 抽象类:定义了汽车的驾驶接口(drive()

  • 工厂模式:定义了如何获得一辆汽车(createCar()

两者结合,才实现了完整的"面向接口编程"理念:既不依赖具体实现类来使用对象,也不依赖具体实现类来创建对象

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
感觉也没多少改善,虽然不用记类名了,但是我还需要记每种选项的字符串
 
 
 
 
 
 

你说到了工厂模式的一个关键痛点!确实,如果只是把 new Dog() 换成 createAnimal("dog"),感觉只是换了一种依赖而已。让我深入解释为什么这实际上是一个重要改进。

问题:还是要记字符串啊!

cpp
// 看起来只是换了个依赖
Animal* pet1 = new Dog();      // 要记类名Dog
Animal* pet2 = create("dog");  // 要记字符串"dog"

// 好像没太大区别?

关键改进:字符串比类名灵活得多!

1. 运行时决定 vs 编译时决定

cpp
// 方案A:直接new(编译时绑定)
void createPet() {
    string userInput = getUserInput();  // 用户输入"cat"
    
    if (userInput == "dog") {
        Animal* pet = new Dog();  // 编译时就知道是Dog
    } else if (userInput == "cat") {
        Animal* pet = new Cat();  // 编译时就知道是Cat
    }
    // 每新增一种动物都要改代码并重新编译!
}

// 方案B:工厂模式(运行时绑定)
class AnimalFactory {
public:
    static Animal* create(const string& type) {
        if (type == "dog") return new Dog();
        if (type == "cat") return new Cat();
        return nullptr;
    }
};

void createPet() {
    string userInput = getUserInput();  // 用户输入"cat"
    
    // 运行时动态创建,代码不需要重新编译!
    Animal* pet = AnimalFactory::create(userInput);
}

2. 配置化:完全不需要记字符串!

cpp
// 从配置文件读取,根本不需要记字符串
#include <fstream>
#include <json/json.h>

class ConfigDrivenFactory {
public:
    static Animal* createFromConfig() {
        // 读取配置文件
        ifstream configFile("animals.json");
        Json::Value config;
        configFile >> config;
        
        // 从配置获取类型
        string animalType = config["default_animal"].asString();
        // 可能是"dog"、"cat"、"bird",但程序员不需要知道!
        
        return create(animalType);
    }
    
private:
    static Animal* create(const string& type) {
        // 工厂内部的映射
        static unordered_map<string, function<Animal*()>> creators = {
            {"dog", []() { return new Dog(); }},
            {"cat", []() { return new Cat(); }},
            {"bird", []() { return new Bird(); }}
        };
        
        if (creators.find(type) != creators.end()) {
            return creators[type]();
        }
        return nullptr;
    }
};

// 客户端使用
int main() {
    // 完全不知道具体的字符串是什么!
    Animal* pet = ConfigDrivenFactory::createFromConfig();
    pet->speak();  // 可能是狗叫、猫叫或鸟叫
    
    return 0;
}

3. 枚举或常量:更好的解决方案

cpp
// 定义枚举,不用记字符串
enum AnimalType {
    DOG,
    CAT, 
    BIRD
};

class AnimalFactory {
public:
    static Animal* create(AnimalType type) {
        switch (type) {
            case DOG: return new Dog();
            case CAT: return new Cat();
            case BIRD: return new Bird();
            default: return nullptr;
        }
    }
};

// 或者用常量
namespace Animals {
    constexpr auto DOG = "dog";
    constexpr auto CAT = "cat"; 
    constexpr auto BIRD = "bird";
}

// 客户端使用
int main() {
    // 使用枚举,类型安全
    Animal* pet1 = AnimalFactory::create(DOG);
    
    // 使用常量,避免拼写错误
    Animal* pet2 = AnimalFactory::create(Animals::CAT);
    
    return 0;
}

真正的好处:创建逻辑的复杂性

工厂模式的核心价值在于处理复杂的创建逻辑,而不仅仅是替换 new

案例1:带缓存的工厂

cpp
class AnimalFactory {
private:
    static unordered_map<string, shared_ptr<Animal>> prototypeCache;
    
    static void initCache() {
        // 预创建原型对象
        prototypeCache["dog"] = make_shared<Dog>();
        prototypeCache["cat"] = make_shared<Cat>();
        prototypeCache["bird"] = make_shared<Bird>();
    }
    
public:
    static shared_ptr<Animal> create(const string& type) {
        // 延迟初始化缓存
        if (prototypeCache.empty()) {
            initCache();
        }
        
        // 使用原型模式克隆,避免重复初始化开销
        if (prototypeCache.find(type) != prototypeCache.end()) {
            return prototypeCache[type]->clone();
        }
        return nullptr;
    }
};

案例2:依赖注入的工厂

cpp
class AnimalFactory {
private:
    // 通过依赖注入配置创建器
    unordered_map<string, function<unique_ptr<Animal>()>> creators;
    
public:
    // 注册创建函数,而不是硬编码
    void registerCreator(const string& type, 
                        function<unique_ptr<Animal>()> creator) {
        creators[type] = creator;
    }
    
    unique_ptr<Animal> create(const string& type) {
        if (creators.find(type) != creators.end()) {
            return creators[type]();
        }
        return nullptr;
    }
};

// 使用
int main() {
    AnimalFactory factory;
    
    // 动态注册,不需要修改工厂代码
    factory.registerCreator("dog", []() {
        auto dog = make_unique<Dog>();
        dog->setAge(2);
        dog->train();
        return dog;
    });
    
    factory.registerCreator("cat", []() {
        auto cat = make_unique<Cat>();
        cat->setColor("orange");
        return cat;
    });
    
    // 客户端使用
    auto pet = factory.create("dog");
    
    return 0;
}

案例3:条件创建的工厂

cpp
class SmartAnimalFactory {
public:
    static unique_ptr<Animal> create() {
        // 基于多种条件自动选择类型
        // 客户端完全不知道选择逻辑
        
        if (isApartmentBuilding()) {
            // 公寓适合养猫
            return make_unique<Cat>();
        } 
        else if (hasLargeYard()) {
            // 有大院子适合养狗
            return make_unique<Dog>();
        }
        else if (isQuietNeighborhood()) {
            // 安静社区可以养鸟
            return make_unique<Bird>();
        }
        
        return nullptr;
    }
    
private:
    static bool isApartmentBuilding() { /* 检查逻辑 */ }
    static bool hasLargeYard() { /* 检查逻辑 */ }
    static bool isQuietNeighborhood() { /* 检查逻辑 */ }
};

// 客户端:一句话搞定,什么参数都不用
auto perfectPet = SmartAnimalFactory::create();

最实际的例子:插件系统

cpp
// 插件接口
class Plugin {
public:
    virtual void execute() = 0;
    virtual ~Plugin() {}
};

// 插件工厂
class PluginFactory {
private:
    static unordered_map<string, function<unique_ptr<Plugin>()>> pluginRegistry;
    
public:
    // 插件动态注册自己
    static void registerPlugin(const string& name,
                              function<unique_ptr<Plugin>()> creator) {
        pluginRegistry[name] = creator;
    }
    
    // 根据配置文件加载插件
    static vector<unique_ptr<Plugin>> loadPlugins() {
        vector<unique_ptr<Plugin>> plugins;
        
        // 读取插件配置
        vector<string> pluginNames = readConfigFile("plugins.config");
        
        for (const auto& name : pluginNames) {
            if (pluginRegistry.find(name) != pluginRegistry.end()) {
                plugins.push_back(pluginRegistry[name]());
            }
        }
        
        return plugins;
    }
};

// 插件实现(在另一个DLL中)
class ImageProcessorPlugin : public Plugin {
public:
    void execute() override { cout << "处理图片" << endl; }
    
    // 自动注册
    class AutoRegister {
    public:
        AutoRegister() {
            PluginFactory::registerPlugin("image_processor", 
                []() { return make_unique<ImageProcessorPlugin>(); });
        }
    };
};

// 自动注册实例
static ImageProcessorPlugin::AutoRegister imageProcessorReg;

// 主程序
int main() {
    // 主程序完全不知道有哪些插件!
    auto plugins = PluginFactory::loadPlugins();
    
    for (auto& plugin : plugins) {
        plugin->execute();  // 可能是图片处理、数据备份、网络监控...
    }
    
    return 0;
}

总结

你的观察很敏锐!如果只是简单替换 new Dog() 为 create("dog"),确实改善有限。但工厂模式的真正威力在于:

  1. 配置化:可以从文件读取,根本不需要记字符串

  2. 复杂逻辑封装:创建过程可能涉及缓存、初始化、验证等

  3. 运行时灵活性:可以动态添加新的创建逻辑

  4. 依赖管理:可以集中管理对象的依赖关系

  5. 插件化架构:支持动态扩展

所以工厂模式不是简单的"不用记类名",而是"将创建逻辑抽象化、配置化、复杂化"的能力。

就像去餐厅:

  • 记类名 = 要知道每个厨师的电话号码

  • 简单工厂 = 记住餐厅电话

  • 真正的工厂 = 用手机App点餐,App会根据你的位置、评分、价格等推荐餐厅,你甚至不需要知道餐厅名字!

posted @ 2026-01-09 01:56  FBshark  阅读(25)  评论(0)    收藏  举报