C++设计模式(工厂模式)

一、介绍

1.动机

在软件系统中,经常面临着创建对象的工作,这些对象有可能是一系列相互依赖的对象;由于需求的变化,需要创建的对象的具体类型经常变化,同时也可能会有更多系列的对象需要被创建。

如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?

 

2.定义

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。——GOF

抽象工厂模式:提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。——GOF

 

3.结构图

工厂方法模式:

42ffb07cfb8048cea5e8a821a0043e38.jpeg

抽象工厂模式:

ff1b2684237c4725ac531ae5b3535925.jpeg

 

4.要点总结

工厂方法模式:

  • Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
  • Factory Method模式通过面向对象的手法,将创建具体对象的工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
  • Factory Method模式解决“单个对象”的需求变化,缺点在于要求创建方法/参数相同。

抽象工厂模式:

  • 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
  • “系列对象”指的是在某一特定系列下的对象之间有相互依赖或相互作用的关系,不同系列的对象之间不能相互依赖。
  • Abstract Factory模式主要在于应对“新系列”的需求变动,其缺点在于难以应对“新对象”的需求变动。

 

 

二、工厂模式

1.概念

工厂模式避免直接使用new运算符来创建产品对象,它提供一个抽象的工厂接口来创建和管理对象的实例化,同时也支持对创建逻辑的封装和扩展。

①工厂模式的优点:

  • 解耦:客户端代码与具体产品的创建逻辑分离,只依赖于抽象产品和工厂接口。
  • 扩展性:增加新产品时只需添加新的具体产品类和相应的具体工厂类,不需要修改现有代码。
  • 重用性:同一个工厂类可以用来创建多个产品,提高代码的复用率。

②工厂模式的缺点:

  • 增加类的数量:可能导致系统中类的数量增加,尤其是在使用抽象工厂模式时。
  • 复杂性:引入额外的抽象层,可能会增加理解和维护的复杂性。

 

2.实现要点

  • 抽象产品:定义一个抽象产品类,它将作为具体产品的共同基类或接口。
  • 具体产品:为每个具体的产品实现一个类,这些类将继承或实现抽象产品类。
  • 抽象工厂:创建一个抽象工厂类,它将提供创建产品的接口。
  • 具体工厂:实现抽象工厂中定义的方法,创建具体的产品对象。
  • 客户端:使用工厂方法来创建对象,但不需要知道具体产品的类。

工厂模式可以分为三种类型:简单工厂模式、工厂方法模式及抽象工厂模式。

 

3.简单工厂模式

通过一个工厂类来创建不同类型的产品实例,根据传递的参数来决定创建哪种具体的产品。

//文具类(抽象产品)
class Stationery {
public:virtual void use() = 0;virtual ~Stationery() {}
};//钢笔类(具体产品)
class Pen :public Stationery {
public:Pen() {cout << "Pen()" << endl;}virtual ~Pen() {cout << "~Pen()" << endl;}virtual void use() override{cout << "Use pen." << endl;}
};//铅笔类(具体产品)
class Pencil :public Stationery {
public:Pencil() {cout << "Pencil()" << endl;}virtual ~Pencil() {cout << "~Pencil()" << endl;}virtual void use() override {cout << "Use pencil." << endl;}
};//枚举类型
enum StationeryType {PEN,PENCIL
};//文具工厂类
class StationeryFactory {
public:static shared_ptr<Stationery> createStationery(StationeryType type) {switch (type) {case PENCIL:return shared_ptr<Stationery>(new Pencil);break;case PEN:return shared_ptr<Stationery>(new Pen);break;defalut:return nullptr;break;}}
};

 测试代码:

shared_ptr<Stationery> pen = StationeryFactory::createStationery(PEN);
pen->use();
shared_ptr<Stationery> pencil = StationeryFactory::createStationery(PENCIL);
pencil->use();

 输出结果;

Pen()
Use pen.
Pencil()
Use pencil.
~Pencil()
~Pen()

 

4.工厂方法模式

将创建具体产品的任务分发给具体的产品工厂,每个具体工厂负责创建对应的具体产品对象。

//交通工具类(抽象类)
class Vehicle {
public:virtual void run() = 0;virtual ~Vehicle() {}
};//汽车类(具体类)
class Car :public Vehicle {
public:virtual void run() override {cout << "The car is running." << endl;}
};//自行车类(具体类)
class Bicycle :public Vehicle {
public:virtual void run() override {cout << "The bicycle is moving." << endl;}
};//交通工具工厂(抽象工厂)
class VehicleFactory {
public:virtual Vehicle* createVehicle() = 0;virtual ~VehicleFactory() {}
};//汽车工厂(具体工厂)
class CarFactory :public VehicleFactory {
public:virtual Vehicle* createVehicle() override {return new Car();}
};//自行车工厂(具体工厂)
class BicycleFactory :public VehicleFactory {
public:virtual Vehicle* createVehicle() override {return new Bicycle();}
};

测试代码: 

VehicleFactory* carFactory = new CarFactory();
Vehicle* car = carFactory->createVehicle();
car->run();
delete car;
delete carFactory;VehicleFactory* bicycleFactory = new BicycleFactory();
Vehicle* bicycle = bicycleFactory->createVehicle();
bicycle->run();
delete bicycle;
delete bicycleFactory;

输出结果: 

The car is running.
The bicycle is moving.

 

5.抽象工厂模式

提供一个抽象的工厂接口以及多个具体工厂类,每个具体工厂类负责创建一种或多种产品。

//桌子类(抽象类)
class Table {
public:virtual void display() = 0;virtual ~Table() {}
};//现代风格桌子(具体类)
class ModernTable :public Table {
public:virtual void display() override {cout << "A modern style table." << endl;}
};//古典风格桌子(具体类)
class ClassicalTable :public Table {
public:virtual void display() override {cout << "A classical style table." << endl;}
};//椅子类(抽象类)
class Chair {
public:virtual void sit() = 0;virtual ~Chair() {}
};//现代风格椅子(具体类)
class ModernChair :public Chair {
public:virtual void sit() override {cout << "Sitting on modern style chair." << endl;}
};//古典风格椅子(具体类)
class ClassicalChair :public Chair {
public:virtual void sit() override {cout << "Sitting on classical style chair." << endl;}
};//沙发类(抽象类)
class Sofa {
public:virtual void relax() = 0;virtual ~Sofa() {}
};//现代风格沙发(具体类)
class ModernSofa :public Sofa {
public:virtual void relax() override {cout << "Relaxing on modern style sofa." << endl;}
};//古典风格沙发(具体类)
class ClassicalSofa :public Sofa {
public:virtual void relax() override {cout << "Relaxing on Classical style sofa." << endl;}
};//家具工厂(抽象工厂)
class FurnitureFactory {
public:virtual Table* createTable() = 0;virtual Chair* createChair() = 0;virtual Sofa* createSofa() = 0;virtual ~FurnitureFactory() {}
};//现代风格家具工厂(具体工厂)
class ModernFurnitureFactory :public FurnitureFactory {
public:virtual Table* createTable() override {return new ModernTable;}virtual Chair* createChair() override {return new ModernChair;}virtual Sofa* createSofa() override {return new ModernSofa;}
};//古典风格家具工厂(具体工厂)
class ClassicalFurnitureFactory :public FurnitureFactory {
public:virtual Table* createTable() override {return new ClassicalTable;}virtual Chair* createChair() override {return new ClassicalChair;}virtual Sofa* createSofa() override {return new ClassicalSofa;}
};

测试代码: 

FurnitureFactory* modernFactory = new ModernFurnitureFactory();
Table* modernTable = modernFactory->createTable();
Chair* modernChair = modernFactory->createChair();
Sofa* modernSofa = modernFactory->createSofa();
modernTable->display();
modernChair->sit();
modernSofa->relax();
delete modernTable;
delete modernChair;
delete modernSofa;FurnitureFactory* classicalFactory = new ClassicalFurnitureFactory();
Table* classicalTable = new ClassicalTable();
Chair* classicalChair = new ClassicalChair();
Sofa* classicalSofa = new ClassicalSofa();
classicalTable->display();
classicalChair->sit();
classicalSofa->relax();
delete classicalTable;
delete classicalChair;
delete classicalSofa;

 输出结果:

A modern style table.
Sitting on modern style chair.
Relaxing on modern style sofa.
A classical style table.
Sitting on classical style chair.
Relaxing on Classical style sofa.

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/62116.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

速度革命:esbuild如何改变前端构建游戏 (1)

什么是 esbuild&#xff1f; esbuild 是一款基于 Go 语言开发的 JavaScript 构建打包工具&#xff0c;以其卓越的性能著称。相比传统的构建工具&#xff08;如 Webpack&#xff09;&#xff0c;esbuild 在打包速度上有着显著的优势&#xff0c;能够将打包速度提升 10 到 100 倍…

java八股-分布式服务的接口幂等性如何设计?

文章目录 接口幂等token Redis分布式锁 原文视频链接&#xff1a;讲解的流程特别清晰&#xff0c;易懂&#xff0c;收获巨大 【新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频面试真题&#xff09;】 https://www.bilibili.com/…

C++:多态的原理

目录 一、多态的原理 1.虚函数表 2.多态的原理 二、单继承和多继承的虚函数表 1、单继承中的虚函数表 2、多继承中的虚函数表 一、多态的原理 1.虚函数表 首先我们创建一个使用了多态的类&#xff0c;创建一个对象来看其内部的内容&#xff1a; #include<iostre…

Local Changes不展示,DevEco Studio的git窗口中没有Local Changes

DevEco Studio的git窗口中&#xff0c;没有Local Changes&#xff0c;怎么设置可以调出&#xff1f; 进入File-->Settings-->Version Control&#xff0c;将Use non-modal commit interface前的勾选框取消勾选&#xff0c;点击OK即可在打开git窗口&#xff0c;就可以看到…

Windows Qtcreator不能debug 调试 qt5 程序

Windows下 Qt Creator 14.0.2 与Qt5.15.2 正常release打包都是没有问题的&#xff0c;就是不能debug&#xff0c;最后发现是两者不兼容导致的&#xff1b; 我使用的是 编译器是 MinGW8.1.0 &#xff0c;这个版本是有问题的&#xff0c;需要更新到最新&#xff0c;我更新的是Mi…

如何搭建C++环境--1.下载安装并调试Microsoft Visual Studio Previerw(Windows)

1.首先&#xff0c;打开浏览器 首先&#xff0c;搜索“Microsoft Visual Studio Previerw” 安装 1.运行VisualStudioSetup (1).exe 无脑一直点继续 然后就到 选择需要的语言 我一般python用pycharm Java&#xff0c;HTML用vscode&#xff08;Microsoft Visual Studio cod…

共享售卖机语音芯片方案选型:WTN6020引领智能化交互新风尚

在共享经济蓬勃发展的今天&#xff0c;共享售卖机作为便捷购物的新形式&#xff0c;正逐步渗透到人们生活的各个角落。为了提升用户体验&#xff0c;增强设备的智能化和互动性&#xff0c;增加共享售卖机的语音功能就显得尤为重要。 共享售卖机语音方案选型&#xff1a; WTN602…

关闭AWS账号后,服务是否仍会继续运行?

在使用亚马逊网络服务&#xff08;AWS&#xff09;时&#xff0c;用户有时可能会考虑关闭自己的AWS账户。这可能是因为项目结束、费用过高&#xff0c;或是转向使用其他云服务平台。然而&#xff0c;许多人对关闭账户后的服务状态感到困惑&#xff0c;我们九河云和大家一起探讨…

新版本PasteSpider开发中专用部署工具介绍(让2GB的服务器也能使用CI/CD,简化你的部署过程)

如果你有linux服务器&#xff0c;可以试试这个PasteSpider&#xff0c;利用容器管理软件(docker/podman)&#xff0c;可以快速上手&#xff01; 拉取镜像并安装 【【【PasteSpider的下载和安装(支持docker的一键模式)】】】 建议使用 最简单的模式SqliteMemoryCache 测试嘛…

【小白学机器学习37】用numpy计算协方差cov(x,y) 和 皮尔逊相关系数 r(x,y)

目录 1 关于1个数组np.array&#xff08;1组数据&#xff09;如何求各种统计数据 2 关于2个数组np.array&#xff08;2组数据&#xff09;如何求数组的相关关系&#xff1f; 2.1 协方差公式和方差公式 2.2 协方差 公式 的相关说明 2.3 用np.cov(x,y,ddof0) 直接求协方差矩…

C++ 11重点总结1

智能指针 智能指针: C11引入了四种智能指针: auto_ptr(已弃用)、unique_ptr、shared_ptr和weak_ptr。智能指针可以更有效地管理堆内存,并避免常见的内存泄漏问题。 shared_ptr: 自定义删除器。 shared_ptr使用引用计数来管理它指向的对象的生命周期。多个shared_ptr实例可以指向…

2024年nvm保姆级安装教程

需求&#xff1a;当前我的nodejs的版本是6.14.10&#xff0c;想切换为更高的版本。故使用nvm工具来实现不同node版本之间的切换 目录 一、删除node二、nvm安装三、配置nvm镜像四、安装所需要的nodejs版本nvm常用命令 一、删除node 第一步&#xff1a;首先在控制面板删除node.j…

Flink--API 之 Source 使用解析

目录 一、Flink Data Sources 分类概览 &#xff08;一&#xff09;预定义 Source &#xff08;二&#xff09;自定义 Source 二、代码实战演示 &#xff08;一&#xff09;预定义 Source 示例 基于本地集合 基于本地文件 基于网络套接字&#xff08;socketTextStream&…

【三维生成】Edify 3D:可扩展的高质量的3D资产生成(英伟达)

标题&#xff1a;Edify 3D: Scalable High-Quality 3D Asset Generation 项目&#xff1a;https://research.nvidia.com/labs/dir/edify-3d demo&#xff1a;https://build.nvidia.com/Shutterstock/edify-3d 文章目录 摘要一、前言二、多视图扩散模型2.1.消融研究 三、重建模型…

Android Framework禁止弹出当前VOLTE不可用的提示窗口

文章目录 VoLTE简介VoLTE 的优势 当前VOLTE不可用的弹窗弹窗代码定位屏蔽弹出窗口 VoLTE简介 VoLTE&#xff08;Voice over LTE&#xff09;是一种基于4G LTE网络的语音通话技术。它允许用户在4G网络上进行高质量的语音通话和视频通话&#xff0c;而不需要回落到2G或3G网络。V…

Element UI 打包探索【3】

目录 第九个命令 node build/bin/gen-cssfile gulp build --gulpfile packages/theme-chalk/gulpfile.js cp-cli packages/theme-chalk/lib lib/theme-chalk 至此&#xff0c;dist命令完成。 解释why Element UI 打包探索【1】里面的why Element UI 打包探索【2】里面…

去哪儿大数据面试题及参考答案

Hadoop 工作原理是什么&#xff1f; Hadoop 是一个开源的分布式计算框架&#xff0c;主要由 HDFS&#xff08;Hadoop 分布式文件系统&#xff09;和 MapReduce 计算模型两部分组成 。 HDFS 工作原理 HDFS 采用主从架构&#xff0c;有一个 NameNode 和多个 DataNode。NameNode 负…

深度学习中的梯度下降算法:详解与实践

梯度下降算法是深度学习领域最基础也是最重要的优化算法之一。它驱动着从简单的线性回归到复杂的深度神经网络模型的训练和优化。作为深度学习的核心工具&#xff0c;梯度下降提供了调整模型参数的方法&#xff0c;使得预测的结果逐步逼近真实值。本文将从梯度下降的基本原理出…

VM+Ubuntu18.04+XSHELL+VSCode环境配置

前段时间换了新电脑&#xff0c;准备安装Linux学习环境&#xff1a;VM虚拟机、Ubuntu18.04操作系统、XSHELL、XFTP远程连接软件、VSCode编辑器等&#xff0c;打算把安装过程记录一下。 1. 虚拟机介绍 为什么要用虚拟机&#xff1f; 想学习Linux操作系统&#xff0c;一般有3种…

《Opencv》基础操作<1>

目录 一、Opencv简介 主要特点&#xff1a; 应用领域&#xff1a; 二、基础操作 1、模块导入 2、图片的读取和显示 &#xff08;1&#xff09;、读取 &#xff08;2&#xff09;、显示 3、 图片的保存 4、获取图像的基本属性 5、图像转灰度图 6、图像的截取 7、图…