工厂模式


工厂模式

前言

在我实现工厂模式的代码时,我遇到了实现这个模型的一些问题,并且继续深究之后,发现理论与实际的基础都缺乏,并因此记录下这次完整的学习过程。

工厂模式封装创建类的过程,使用统一的接口来实例化不同的产品类,符合开放封闭的原则(对接口开放,对修改封闭),解决的是创建“什么对象”的问题,单例模式解决的是创建“多少对象“的问题。

实现工厂模式

正确代码示例:

#include <iostream>
using namespace std;

enum ProductType {
    TypeA,
    TypeB,
    TypeC
};

class Product {
public:
    // 错误修复1:删除构造函数的virtual关键字
    Product() {};
    virtual void eat() = 0; // 纯虚函数,标记抽象类
    // 错误修复2:为纯虚析构提供空实现
    virtual ~Product() {};
};

class ProductA : public Product {
public:
    ProductA() {
        cout << "Produce A" << endl;
    }
    void eat() { cout << "eat A" << endl; }
    ~ProductA() {
        cout << "~ProductA" << endl;
    }
};

class ProductB : public Product {
public:
    ProductB() {
        cout << "Produce B" << endl;
    }
    void eat() { cout << "eat B" << endl; }
    ~ProductB() {
        cout << "~ProductB" << endl;
    }
};

class Factory {
public:
    Factory() : product(nullptr) {}
    Product* produceProduct(ProductType productType) {
        // 错误修复3:创建新对象前释放旧对象,避免内存泄漏
        if (product) {
            delete product;
            product = nullptr;
        }
        switch (productType) {
            case TypeA:
                product = new ProductA();
                break;
            case TypeB:
                product = new ProductB();
                break;
            default:
                product = new ProductA();
                break;
        }
        return product;
    }
    ~Factory() {
        if (product) {
            delete product;
            product = nullptr;
        }
    }
private:
    Product* product;
};

void testFuncEat() {
    Factory f;
    Product* p = f.produceProduct(TypeA);
    p->eat();
}

int main() {
    testFuncEat();
    return 0;
}

其中需要修复的地方就是我之前放下的错误:

犯下的错误与思考

错误一

构造函数不能声明为:virtual

virtual Product(){}; // 错误1:构造函数声明为virtual

虚表指针的初始化时机就是在构造函数中,virtual关键字用于支持运行时多态,依赖对象的虚函数表(vtable)。但构造函数的作用是创建并初始化对象,在对象完全创建前,虚函数表尚未初始化,无法实现多态;且调用构造函数时必须明确具体类类型,无法延迟决定调用哪个构造函数,C++标准禁止构造函数为虚函数。

错误二

析构函数无法无法定义为纯虚函数

virtual ~Product() {}; // 错误2:纯虚析构仅声明未定义

纯虚析构的=0仅用于标记类为抽象类,而非“无需实现”。析构函数遵循“先子类、后父类”的链式调用规则,子类析构执行完后会自动调用父类析构,若父类纯虚析构无实现,链接器会找不到对应函数体,导致报错。

错误三

构建新的对象前没有考虑原始资源的释放。

// 修复3:创建新对象前释放旧对象,避免内存泄漏
if (product) {
    delete product;
    product = nullptr;
}

明确内存释放责任,由Factory统一管理product指针的生命周期,外部仅使用指针,不执行delete操作;同时在Factory创建新对象前,释放旧对象,避免内存泄漏。


文章作者: AllenMirac
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AllenMirac !
  目录