C++|设计模式(三)|抽象工厂模式

抽象工厂模式仍然属于创建型模式,我们在【简单工厂和工厂方法模式】这篇文章中,描述了简单工厂和工厂方法模式,并在文末,简单介绍了工厂方法模式的局限性。

本文将通过汽车工厂的例子继续来阐述使用抽象工厂模式相比较于工厂方法模式的优势。

文章目录

工厂方法模式回顾

工厂方法模式通过允许类将实例化延迟到子类中来实现,使得增加新的产品类不需要修改现有系统的代码。例如,一个汽车制造商需要不同类型的汽车,如宝马、奥迪等,每种汽车的制造过程可能不同:

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>
using namespace std;

class Car {
public:
    Car(string name) : name_(name) { }
    virtual ~Car(){}
    virtual void show() = 0;
protected:
    string name_;
};

class Bmw : public Car {
public:
    Bmw(string name) : Car(name) { }
    void show() { cout << "获得一辆宝马汽车 " << name_ <<endl; }
};

class Audi : public Car {
public:
    Audi(string name) : Car(name) { }
    void show() { cout << "获得一辆奥迪汽车 " << name_ << endl; }
};

//工厂方法
class Factory {
public:
    virtual ~Factory() {}
    virtual Car* createCar(string name) = 0; //工厂方法
};

//宝马工厂
class BMWFactory : public Factory {
public:
    Car* createCar(string name) { return new Bmw(name); }
};
//奥迪工厂
class AudiFactory : public Factory {
public:
    Car* createCar(string name) { return new Audi(name); }
};

int main () {
    unique_ptr<Factory> bmwFactory(new BMWFactory());
    unique_ptr<Factory> audiFactory(new AudiFactory());
    unique_ptr<Car> p1(bmwFactory->createCar("X6"));
    unique_ptr<Car> p2(audiFactory->createCar("A8"));

    p1->show();
    p2->show();

    return 0;
}

现在,我们考虑这样一种情况,如果我们现在要生产的产品是一组有关联的产品簇怎么办?难道我们像工厂方法一样,又新建立一个工厂来生产该产品吗?

比如说,我们之前有了奥迪工厂和宝马工厂,现在我们需要生产奥迪车灯和宝马车灯,难道又建立奥迪车灯工厂吗?

这样的话,最后我们需要管理的工厂(类)那也太多了,所以,很容易想到:

我们应该对一组有关联关系的产品簇提供产品对象的统一创建。这就是抽象工厂模式。

抽象工厂模式

我们把之前的工厂方法类写成抽象工厂类,并且里面提供创建车灯的方法,

并且,我们直接在宝马工厂和奥迪工厂去创建车灯:

cpp 复制代码
//系列产品一:汽车
class Car {
public:
    Car(string name) : name_(name) { }
    virtual ~Car(){}
    virtual void show() = 0;
protected:
    string name_;
};
class Bmw : public Car {
public:
    Bmw(string name) : Car(name) { }
    void show() { cout << "获得一辆宝马汽车 " << name_ <<endl; }
};
class Audi : public Car {
public:
    Audi(string name) : Car(name) { }
    void show() { cout << "获得一辆奥迪汽车 " << name_ << endl; }
};
//系列产品二:车灯
class Light {
public:
    virtual ~Light() {}
    virtual void show() = 0;
};
class BmwLight : public Light{
public:
    void show() { cout << "BMW light!" << endl;};
};
class AudiLight : public Light{
public:
    void show() { cout << "Audi light!" << endl;};
};

//工厂方法 =》 抽象工厂(对一组有关联关系的产品簇提供产品对象的统一创建)
class AbstractFactory {
public:
    virtual ~AbstractFactory() {}
    virtual Car* createCar(string name) = 0; //工厂方法 创建汽车
    virtual Light* createLight() = 0; // 工厂方法 创建汽车关联的产品--车灯
};

//宝马工厂
class BMWFactory : public AbstractFactory {
public:
    Car* createCar(string name) { return new Bmw(name); }
    Light* createLight() {
        return new BmwLight();
    }
};
//奥迪工厂
class AudiFactory : public AbstractFactory {
public:
    Car* createCar(string name) { return new Audi(name); }
    Light* createLight() {
        return new AudiLight();
    }
};

代码使用

cpp 复制代码
int main () {
    unique_ptr<AbstractFactory> bmwFactory(new BMWFactory());
    unique_ptr<AbstractFactory> audiFactory(new AudiFactory());
    unique_ptr<Car> p1(bmwFactory->createCar("X6"));
    unique_ptr<Car> p2(audiFactory->createCar("A8"));
    unique_ptr<Light> l1(bmwFactory->createCarLight());
    unique_ptr<Light> l2(audiFactory->createCarLight());

    p1->show();
    l1->show();

    p2->show();
    l2->show();

    return 0;
}

抽象工厂的局限性

我们设想这样一种场景,比如说我们的宝马工厂需要创建一个新的类对象(产品),但是奥迪工厂并不需要,但是如果宝马工厂想要创建该类,

我们也比赛在抽象工厂类中去定义这样一个虚函数,尽管奥迪工厂并不需要创建该类对象,他还是不得不去重写该虚函数。这样是不符合逻辑的。

总结:

简单工厂Simple Factory:

优点:把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象,用户不用自己负责new对象,不用了解对象创建的详细过程

缺点:提供创建对象实例的接口函数不闭合,不能对修改关闭

工厂方法Factory Method:

优点:Fatcory基类,提供了一个纯虚函数(创建产品),定义派生类(具体产品的工厂)负责创建对应的产品,可以做到不同的产品,在不同的工厂里面创建,能够对现有工厂,以及产品的修改关闭

缺点:实际上,很多产品是有管理关系的,属于一个产品簇,不应该放在不同的工厂里面去创建,这样一是不符合实际的产品对象创建逻辑,二是工厂类太多了,不好维护

抽象工厂Abstract Factory

优点:把有关联关系的,属于一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面AbstractFactory类,派生类(具体产品的工厂)应该负责创建该产品簇里面所有的产品。

相关推荐
xu_yule1 小时前
算法基础(数论)—费马小定理
c++·算法·裴蜀定理·欧拉定理·费马小定理·同余方程·扩展欧几里得定理
宇宙超级无敌暴龙战士5 小时前
旮旯c语言三个任务
c++·c
BanyeBirth6 小时前
C++差分数组(二维)
开发语言·c++·算法
Fcy6486 小时前
C++ map和multimap的使用
开发语言·c++·stl
CC.GG7 小时前
【C++】STL容器----unordered_map和unordered_set的使用
java·数据库·c++
lengjingzju7 小时前
基于IMake的 GCC 编译与链接选项深度解析:构建高效、安全、可调试的现代软件
c++·安全·性能优化·软件构建·开源软件
xu_yule8 小时前
算法基础(数论)—算法基本定理
c++·算法·算数基本定理
CoderCodingNo8 小时前
【GESP】C++五级真题(结构体排序考点) luogu-B3968 [GESP202403 五级] 成绩排序
开发语言·c++·算法
爱学习的小可爱卢9 小时前
JavaEE进阶——Spring核心设计模式深度剖析
java·spring·设计模式
星轨初途10 小时前
郑州轻工业大学2025天梯赛解题
c++·经验分享·笔记·算法·链表·剪枝