当前位置: 首页 > news >正文

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

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

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

文章目录

  • 工厂方法模式回顾
  • 抽象工厂模式
    • 代码使用
    • 抽象工厂的局限性

工厂方法模式回顾

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

#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;
}

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

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

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

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

抽象工厂模式

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

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

//系列产品一:汽车
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();}
};

代码使用

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类,派生类(具体产品的工厂)应该负责创建该产品簇里面所有的产品。

http://www.lryc.cn/news/358317.html

相关文章:

  • AVB协议分析(一) FQTSS协议介绍
  • 一个程序员的牢狱生涯(44)询问
  • 刷爆leetcode第六期
  • 汇舟问卷:国外问卷调一天900
  • openresty完美替代nginx
  • 深入解析:Element Plus 与 Vite、Nuxt、Laravel 的结合使用
  • 使ssh连接Linux服务器一直不掉线
  • 2024-05-29 blue-VH-driver-对外接口的并行调用-设计与思考
  • ubuntu安装
  • Rosetta PyRosetta 源码包 安装包 下载
  • C++ 进阶(3)虚函数表解析
  • 2024年新算法-秘书鸟优化算法(SBOA)优化BP神经网络回归预测
  • kafka-主题创建(主题操作的命令)
  • [日常开发] 数据库主从延迟问题
  • Python高层解雇和客户活跃度量化不确定性模型
  • 【IOT】OrangePi+HomeAssistant+Yolov5智能家居融合
  • Python 点云裁剪
  • Presto 从提交SQL到获取结果 源码详解(2)
  • Python的类全面系统学习
  • 信号处理中简单实用的方法
  • Jeecg | 如何解决 ERR Client sent AUTH, but no password is set 问题
  • 数据容器:set(集合) 更新啦!
  • 算法入门----小话算法(1)
  • Vue | 自定义组件双向绑定基础用法
  • python使用modbustcp协议与PLC进行简单通信
  • mongodb在游戏开发领域的优势
  • 大数据Scala教程从入门到精通第十篇:Scala在IDEA中编写Hello World代码的简单说明
  • 【SPSS】基于因子分析法对水果茶调查问卷进行分析
  • ElasticSearch学习篇12_《检索技术核心20讲》基础篇
  • Reids高频面试题汇总总结