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

常见的设计模式(3)工厂模式

目录

一、为什么不用new,而需要工厂模式?

二、简单工厂

三、工厂模式

四、抽象工厂


        工厂模式是设计模式中最常用的创建型模式之一,它解决了直接使用new关键字创建对象时带来的诸多问题。本文将通过对比直接new的方式,详细讲解工厂模式的三种形式 —— 简单工厂、工厂方法和抽象工厂,并通过生活实例和代码示例帮助新手理解它们的优势和应用场景。

一、为什么不用new,而需要工厂模式?

        在初学C++的时候,我们都是直接使用new关键字来定义对象的,例如:

Pizza* pizza = new CheesePizza();

这种方式看似简单,但在实际开发中会带来一系列问题:

(1)耦合度过高:创建一个对象必须要完整的知道对象的名字,当需要更换类型时,所有用new的地方都要重新修改成别的类。

(2)违反开闭原则:当添加新类型的时候,需要修改所有创建对象的代码

(3)如果创建对象后还需要进行一系列初始化工作,会让业务代码多出很多初始化工作,代码逻辑冗杂,违反单一职能原则。

工厂模式的核心思想是:将对象的创建与使用分离。由专门的 工厂类来负责对象的创建,从而解决上述问题。

        类比我们生活中的例子:你想要购买一辆汽车,你不需要手动new,然后对汽车做一系列的设置才能使用。如果你去4s店购买,所有的设置他都帮你完成了,你拿到手的就是可以直接使用的汽车。工厂模式就是专业的事情交给专业的类去做,达到职能解耦的效果。

二、简单工厂

        简单工厂模式由一个工厂类根据传入的参数,决定创建哪一种产品类的实例。它不属于 GoF 的 23 种设计模式,但在实际开发中应用广泛,是工厂模式的基础形式。

        假设你经营一家水果店,顾客想要什么水果你都直接给他。

        简单工厂模式就好像一个小作坊,只要产品是一个品类的都能做,使用的时候只需要告诉小作坊你要该类下面的什么产品即可。

//简单工厂class Fruit
{
public:Fruit() {}virtual void show() = 0;
};class Apple :public Fruit
{void show()override{std::cout << "我是一个苹果" << std::endl;}
};class Banana:public Fruit
{
public:void show()override{std::cout << "我是一个香蕉" << std::endl;}
};class FruitFactory
{
public:std::shared_ptr<Fruit> CreateFruit(const std::string & name){if (name=="苹果"){return std::make_shared<Apple>();}else{return std::make_shared<Banana>();}}
};int main()
{//创建工厂类FruitFactory ff;std::shared_ptr<Fruit> fruit=ff.CreateFruit("苹果");fruit->show();fruit = ff.CreateFruit("香蕉");fruit->show();return 0;
}

        简单工厂模式实现较为简单,便于理解工厂模式的原理。但是他严重违反了开闭原则,当想要新增水果品类的时候,需要修改工厂类。

三、工厂模式

        正是因为简单工厂违反了开闭原则,工厂模式则是把产品和工厂绑定起来,一个工厂只负责生产一种产品,当需要新增新的产品的时候,直接扩展工厂即可。

        ⼯⼚⽅法模式: 在简单⼯⼚模式下新增多个⼯⼚,多个产品,每个产品对应⼀个⼯⼚。假设现在有A、B 两种产品,则开两个⼯⼚,⼯⼚ A 负责⽣产产品 A,⼯⼚ B 负责⽣产产品 B,⽤⼾只知道产品的⼯⼚名,⽽不知道具体的产品信息,⼯⼚不需要再接收客⼾的产品类别,⽽只负责⽣产产品。

//工厂模式
class Fruit
{
public:Fruit() {}virtual void show() = 0;
};class Apple :public Fruit
{void show()override{std::cout << "我是一个苹果" << std::endl;}
};class Banana:public Fruit
{
public:void show()override{std::cout << "我是一个香蕉" << std::endl;}
};class FruitFactory
{
public:virtual std::shared_ptr<Fruit> CreateFruit() = 0;
};class AppleFactory:public FruitFactory
{
public:std::shared_ptr<Fruit> CreateFruit(){return std::make_shared<Apple>();}
};class BananaFactory :public FruitFactory
{
public:std::shared_ptr<Fruit> CreateFruit(){return std::make_shared<Banana>();}
};int main()
{//创建苹果工厂std::shared_ptr<FruitFactory> appleff(new AppleFactory());std::shared_ptr<Fruit> apple = appleff->CreateFruit();apple->show();//创建香蕉工厂std::shared_ptr<FruitFactory> bananaff(new BananaFactory());std::shared_ptr<Fruit> banana = bananaff->CreateFruit();banana->show();return 0;
}

工厂模式虽然符合了开闭原则,方便后续扩展。但是当产品类很多的时候,这会使得系统中类的个数成倍增加,在⼀定程度上增加了系统的耦合度。

四、抽象工厂

        抽象⼯⼚模式: ⼯⼚⽅法模式通过引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责太重的问题,但由于⼯⼚⽅法模式中的每个⼯⼚只⽣产⼀类产品,可能会导致系统中存在⼤量的⼯⼚类,势必会增加系统的开销。此时,我们可以考虑将⼀些相关的产品组成⼀个产品族(位于不同产品等级结构中功能相关联的产品组成的家族),由同⼀个⼯⼚来统⼀⽣产,这就是抽象⼯⼚模式的基本思想。

        简单来说,抽象工厂是用来生产一系列配套产品的设计模式。在之前的工厂模式中,每一个产品都对应一个工厂类,一系列产品容易拿混。而简单工厂不利于扩展新系列产品。抽象工厂模式本质是对简单工厂的抽象,当每个系列产品的数量种类都一致的时候,扩展新系列比较方便。不过一旦想要在每个系列中插入新产品,则严重违反了开闭原则,因为他本质是简单工厂。

        

#include <iostream>
#include <memory>
#include <string>
using namespace std;// 抽象产品1:水果(产品类别1)
class Fruit {
public:virtual ~Fruit() = default;virtual void show() = 0; // 展示水果信息(含产地,体现产品族)
};// 具体产品1-1:北方苹果(属于“北方产品族”)
class NorthApple : public Fruit {
public:void show() override {cout << "我是北方农场的苹果" << endl;}
};// 具体产品1-2:南方香蕉(属于“南方产品族”)
class SouthBanana : public Fruit {
public:void show() override {cout << "我是南方农场的香蕉" << endl;}
};// 抽象产品2:动物(产品类别2)
class Animal {
public:virtual ~Animal() = default;virtual void voice() = 0; // 展示动物叫声(含产地,体现产品族)
};// 具体产品2-1:北方羊(属于“北方产品族”)
class NorthSheep : public Animal {
public:void voice() override {cout << "北方农场的羊:咩咩咩" << endl;}
};// 具体产品2-2:南方狗(属于“南方产品族”)
class SouthDog : public Animal {
public:void voice() override {cout << "南方农场的狗:汪汪汪" << endl;}
};// 抽象工厂:定义“产品族”的创建接口(必须覆盖所有产品类别)
class FarmFactory {
public:virtual ~FarmFactory() = default;virtual shared_ptr<Fruit> createFruit() = 0;  // 创建本产品族的水果virtual shared_ptr<Animal> createAnimal() = 0; // 创建本产品族的动物
};// 具体工厂1:北方农场工厂(创建“北方产品族”的所有产品)
class NorthFarmFactory : public FarmFactory {
public:shared_ptr<Fruit> createFruit() override {return make_shared<NorthApple>(); // 北方产品族的水果:北方苹果}shared_ptr<Animal> createAnimal() override {return make_shared<NorthSheep>(); // 北方产品族的动物:北方羊}
};// 具体工厂2:南方农场工厂(创建“南方产品族”的所有产品)
class SouthFarmFactory : public FarmFactory {
public:shared_ptr<Fruit> createFruit() override {return make_shared<SouthBanana>(); // 南方产品族的水果:南方香蕉}shared_ptr<Animal> createAnimal() override {return make_shared<SouthDog>(); // 南方产品族的动物:南方狗}
};// 工厂生产者(可选,用于简化工厂创建,本质是简单工厂)
class FactoryProducer {
public:static shared_ptr<FarmFactory> getFarmFactory(const string& farmType) {if (farmType == "北方农场") {return make_shared<NorthFarmFactory>();} else if (farmType == "南方农场") {return make_shared<SouthFarmFactory>();}return nullptr;}
};int main() {// 1. 获取“北方农场工厂”(对应“北方产品族”)shared_ptr<FarmFactory> northFarm = FactoryProducer::getFarmFactory("北方农场");shared_ptr<Fruit> northFruit = northFarm->createFruit();shared_ptr<Animal> northAnimal = northFarm->createAnimal();northFruit->show();    // 输出:我是北方农场的苹果northAnimal->voice();  // 输出:北方农场的羊:咩咩咩// 2. 获取“南方农场工厂”(对应“南方产品族”)shared_ptr<FarmFactory> southFarm = FactoryProducer::getFarmFactory("南方农场");shared_ptr<Fruit> southFruit = southFarm->createFruit();shared_ptr<Animal> southAnimal = southFarm->createAnimal();southFruit->show();    // 输出:我是南方农场的香蕉southAnimal->voice();  // 输出:南方农场的狗:汪汪汪return 0;
}

抽象⼯⼚模式适⽤于⽣产多个⼯⼚一系列产品衍⽣的设计模式,增加新的产品会很复杂,需要对原有系统进⾏较⼤的修改,甚⾄需要修改抽象层代码,违背了“开闭原则”。


文章转载自:

http://XhgTrrCI.jtrqn.cn
http://9vDVb6Li.jtrqn.cn
http://3wCv4aZP.jtrqn.cn
http://WFWZlHRb.jtrqn.cn
http://mf241m4j.jtrqn.cn
http://EvBQBR1v.jtrqn.cn
http://ACWUwY3u.jtrqn.cn
http://PRPYnf0V.jtrqn.cn
http://t9q8zXZq.jtrqn.cn
http://MOqp0qse.jtrqn.cn
http://KwCx5aV2.jtrqn.cn
http://HgD8R7aD.jtrqn.cn
http://u2DcDL7v.jtrqn.cn
http://4Jhbki5N.jtrqn.cn
http://0Rlhhoe6.jtrqn.cn
http://FL4gNQoL.jtrqn.cn
http://loa3uiDP.jtrqn.cn
http://Hmodnq5k.jtrqn.cn
http://Js1gs8Kh.jtrqn.cn
http://w46Ciot5.jtrqn.cn
http://UiIvlheI.jtrqn.cn
http://sG4neOwf.jtrqn.cn
http://7nRyN52P.jtrqn.cn
http://m9l1bEtF.jtrqn.cn
http://gkBLBZDx.jtrqn.cn
http://yXQsPrU2.jtrqn.cn
http://X85st4YM.jtrqn.cn
http://bj1XVsWz.jtrqn.cn
http://JYSpYde4.jtrqn.cn
http://tkIiVIcp.jtrqn.cn
http://www.dtcms.com/a/366356.html

相关文章:

  • ansible-角色
  • 《设计模式之禅》笔记摘录 - 19.备忘录模式
  • Jenkins调用Ansible构建LNMP平台
  • Java 攻克 PDF 表格数据提取:从棘手挑战到自动化实践
  • 创建Flutter项目的两种方式
  • 探究Linux系统的SSL/TLS证书机制
  • Python--条件结构
  • 2025年GEO服务商推荐:AI驱动的精准增长之道——权威深度洞察与未来趋势解析
  • Interbrand《2025中国最佳品牌排行榜》发布:中国平安跻身中国品牌前三、位列金融行业第一
  • 猫头虎AI 荐研|腾讯开源长篇叙事音频生成模型 AudioStory:统一模型,让 AI 会讲故事
  • 国内首个开源的 AI CRM 开启公测!
  • 汉诺塔递归过程推导(详细+省流)
  • MySQL高可用之组复制(MGR)
  • 单串口服务器-工业级串口联网解决方案
  • 数据库中事务、指令、写法解读
  • 【Cesium】介绍及基础使用
  • 新手向:使用 DeepSeek 帮助自己的工作
  • React Hooks深度解析:useState、useEffect及自定义Hook最佳实践
  • Shadcn UI – 开发者首选的高性能、高定制化 React 组件库
  • 【Day 20】148.排序链表
  • Flash Attention vs Paged Attention:大语言模型注意力计算的内存管理革命
  • 设计模式:中介者模式(Mediator Pattern)
  • 从Java全栈到Vue3:一个程序员的面试实战记录
  • 虚拟环境克隆
  • leetcode算法刷题的第二十六天
  • STM32传感器模块编程实践(十五)DIY语音对话控制+满溢检测智能垃圾桶模型
  • 5.7 点云公开数据集——3D形状分类/部件分割
  • 食物分类案例优化 调整学习率和迁移学习
  • Python快速入门专业版(二):print 函数深度解析:不止于打印字符串(含10+实用案例)
  • 阿里云-基于通义灵码实现高效 AI 编码 | 1 | 在 Visual Studio Code 中安装和使用灵码