工厂方法模式(大话设计模式)C/C++版本
工厂方法模式
C++
参考:https://www.cnblogs.com/Galesaur-wcy/p/15926711.html
#include <iostream>
#include <memory>
using namespace std;// 运算类
class Operation
{
private:double _NumA;double _NumB;public:void SetNumA(){cout << "Enter a double number: ";if (!(cin >> _NumA))throw "It must be a number";}double GetNumA(){return _NumA;}void SetNumB(){cout << "Enter a double number: ";if (!(cin >> _NumB))throw "It must be a number";}double GetNumB(){return _NumB;}virtual double GetResult(){int result = 0;return result;}
};class OperationAdd : public Operation
{
public:double GetResult(){double result = GetNumA() + GetNumB();return result;}
};class OperationSub : public Operation
{
public:double GetResult(){double result = GetNumA() - GetNumB();return result;}
};class OperationMul : public Operation
{
public:double GetResult(){double result = GetNumA() * GetNumB();return result;}
};class OperationDiv : public Operation
{
public:double GetResult(){if (GetNumB() == 0){throw "The divisor cannot be 0";}double result = GetNumA() / GetNumB();return result;}
};class Factory
{
public:virtual Operation *CreatOperation() = 0;
};class AddFactory : public Factory
{
public:Operation *CreatOperation(){return new OperationAdd();}
};class SubFactory : public Factory
{
public:Operation *CreatOperation(){return new OperationSub();}
};class MulFactory : public Factory
{
public:Operation *CreatOperation(){return new OperationMul();}
};class DivFactory : public Factory
{
public:Operation *CreatOperation(){return new OperationDiv();}
};/* 封装一下用户选择工厂创建的过程(属于客户端代码) */
Factory * CreatFactory(char operator_type)
{switch (operator_type){case '+':return new AddFactory;break;case '-':return new SubFactory;break;case '*':return new MulFactory;break;case '/':return new DivFactory;break;default:throw "Error input operator!";break;}return nullptr;
}int main()
{cout << "Choose an operation:";char operator_char;cin >> operator_char;try{//unique_ptr<Factory> fac = unique_ptr<Factory>(CreatFactory(operator_char));//智能指针更安全Factory* fac = CreatFactory(operator_char);//unique_ptr<Operation> oper = unique_ptr<Operation>(fac->CreatOperation());Operation* oper = fac->CreatOperation();oper->SetNumA();oper->SetNumB();cout << "result is: " << oper->GetResult() << endl;}catch (const char *err){cerr << err << endl;return -1;}return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>typedef struct Operation
{double NumA;double NumB;double (*GetResult)(struct Operation *);void (*SetNumA)(struct Operation *);void (*SetNumB)(struct Operation *);
} Operation;typedef struct OperationAdd
{Operation base; // 设置为第一个成员属性,模拟继承
} OperationAdd;typedef struct OperationSub
{Operation base;
} OperationSub;typedef struct OperationMul
{Operation base;
} OperationMul;typedef struct OperationDiv
{Operation base;
} OperationDiv;double OperationAddGetResult(struct Operation *op)
{OperationAdd *add = (OperationAdd *)op;return add->base.NumA + add->base.NumB;
}double OperationSubGetResult(struct Operation *op)
{OperationSub *sub = (OperationSub *)op;return sub->base.NumA - sub->base.NumB;
}double OperationMulGetResult(struct Operation *op)
{OperationMul *mul = (OperationMul *)op;return mul->base.NumA * mul->base.NumB;
}double OperationDivGetResult(struct Operation *op)
{OperationDiv *div = (OperationDiv *)op;if (div->base.NumB == 0){fputs("The divisor cannot be 0\n", stderr);exit(EXIT_FAILURE);}return div->base.NumA / div->base.NumB;
}typedef struct Factory
{Operation* (*CreatOperation)();
}Factory;typedef struct FactoryAdd
{Factory base;
} FactoryAdd;typedef struct FactorySub
{Factory base;
} FactorySub;typedef struct FactoryMul
{Factory base;
} FactoryMul;typedef struct FactoryDiv
{Factory base;
} FactoryDiv;void SetNumA(Operation *ope)
{printf("Enter a double number: ");if (scanf("%lf", &ope->NumA) != 1){fputs("It must be a number\n", stderr);exit(EXIT_FAILURE);}
}void SetNumB(Operation *ope)
{printf("Enter a double number: ");if (scanf("%lf", &ope->NumB) != 1){fputs("It must be a number\n", stderr);exit(EXIT_FAILURE);}
}Operation *CreatOperationAdd()
{Operation *op = malloc(sizeof(Operation));op->GetResult = OperationAddGetResult;op->SetNumA = SetNumA;op->SetNumB = SetNumB;return op;
}Operation *CreatOperationSub()
{Operation *op = malloc(sizeof(Operation));op->GetResult = OperationSubGetResult;op->SetNumA = SetNumA;op->SetNumB = SetNumB;return op;
}Operation *CreatOperationMul()
{Operation *op = malloc(sizeof(Operation));op->GetResult = OperationMulGetResult;op->SetNumA = SetNumA;op->SetNumB = SetNumB;return op;
}Operation *CreatOperationDiv()
{Operation *op = malloc(sizeof(Operation));op->GetResult = OperationDivGetResult;op->SetNumA = SetNumA;op->SetNumB = SetNumB;return op;
}Factory *CreateFactory(char op)
{Factory *fac = NULL;switch (op){case '+':fac = malloc(sizeof(FactoryAdd));fac->CreatOperation = CreatOperationAdd;break;case '-':fac = malloc(sizeof(FactorySub));fac->CreatOperation = CreatOperationSub;break;case '*':fac = malloc(sizeof(FactoryMul));fac->CreatOperation = CreatOperationMul;break;case '/':fac = malloc(sizeof(FactoryDiv));fac->CreatOperation = CreatOperationDiv;break;default:fputs("Error input operator!\n", stderr);return NULL;}return fac;
}int main()
{printf("Choose an operation: ");char operator_char = getchar();Factory* fac = CreateFactory(operator_char);Operation *oper = fac->CreatOperation();if (!oper)return EXIT_FAILURE;oper->SetNumA(oper);oper->SetNumB(oper);printf("Result is: %f\n", oper->GetResult(oper));free(oper);return 0;
}
对比简单工厂模式
简单工厂模式例子
- 给四种运算新建了四个具体工厂类
- 将简单工厂类模式中的工厂创建逻辑判断,移到了客户端代码中
工厂方法模式这样做的目的就是:对创建工厂类的修改关闭,对具体工厂类的扩展开放。
思维思路:
- 简单工厂类中的创建工厂类中直接与具体的运算符号产生了依赖,不易于扩展(后期增加运算符,得直接修改工厂类)。
- 为了降低耦合,根据依赖倒置的原则(细节依赖抽象),将创建工厂类的分支判断直接改成对应的具体工厂类。
相关文章:

工厂方法模式(大话设计模式)C/C++版本
工厂方法模式 C 参考:https://www.cnblogs.com/Galesaur-wcy/p/15926711.html #include <iostream> #include <memory> using namespace std;// 运算类 class Operation { private:double _NumA;double _NumB;public:void SetNumA(){cout << &…...

[NCTF 2018]flask真香
打开题目后没有提示框,尝试扫描后也没有什么结果,猜想是ssti。所以尝试寻找ssti的注入点并判断模版。 模版判断方式: 在url地址中输入{7*7} 后发现不能识别执行。 尝试{{7*7}} ,执行成功,继续往下走注入{{7*7}},如果执…...

性能测试3【搬代码】
1.Linux服务器性能分析命令及详解 2.GarafanainfluxDB监控jmeter数据 3.GarafanaPrometheus监控服务器和数据库性能 4.性能瓶颈分析以及性能调优方案详解 一、无界面压测时, top load average:平均负载 htop 二、Garafana监控平台 传统项目:centosphpm…...

<tesseract><opencv><Python>基于python和opencv,使用ocr识别图片中的文本并进行替换
前言 本文是在python中,利用opencv处理图片,利用tesseractOCR来识别图片中的文本并进行替换的一种实现方法。 环境配置 系统:windows 平台:visual studio code 语言:python 库:pyqt5、opencv、tesseractOCR 代码介绍 本文程序功能实现,主要依赖于tesseractOCR这个库,…...

海南云亿商务咨询有限公司解锁抖音电商新纪元
在当今数字化浪潮中,抖音电商以其独特的魅力和强大的用户基础,迅速成为企业营销的新宠。海南云亿商务咨询有限公司,作为专注于抖音电商服务的领先企业,凭借专业的团队和丰富的经验,为众多企业提供了高效、精准的电商服…...

arm64架构 统信UOS搭建PXE无盘启动Linux系统(麒麟桌面为例)
arm64架构 统信UOS搭建PXE无盘启动Linux系统(麒麟桌面为例) 搞了好久搞得头疼哎 1、准备服务器UOS服务器 准备服务IP 这里是192.168.1.100 1.1、安装程序 yum install -y dhcp tftp tftp-server xinetd nfs-utils rpcbind 2、修改配置 2.1、修改dhcpd.c…...

SpringBoot 实现 阿里云语音通知(SingleCallByTts)
目录 一、准备工作1.开通 阿里云语音服务2.申请企业资质3.创建语音通知模板,审核通过4.调用API接口---SingleCallByTts5.调试API接口---SingleCallByTts 二、代码实现1.导入依赖 com.aliyun:aliyun-java-sdk-dyvmsapi:3.0.22.创建工具类,用于发送语音通知…...

IDEA 连接GitHub仓库并上传项目(同时解决SSH问题)
目录 1 确认自己电脑上已经安装好Git 2 添加GitHub账号 2.1 Setting -> 搜索GitHub-> ‘’ -> Log In with Token 2.2 点击Generate 去GitHub生成Token 2.3 勾选SSH后其他不变直接生成token 2.4 然后复制token添加登录账号即可 3 点击导航栏中VCS -> Create…...

vue/react/js 常用的原生获取当前页面的url网址的相关方法
目录 第一章 场景 第二章 总结 第一章 场景 最近实现需求时遇到这么一种情况: 本地url —— 线上url —— 需求:需要将token清除掉 注意事项:token不是#/后面的参数,说明并不是我们前端返回的,vue路由的方法使用不…...

java-final 关键字
## Java中的final关键字 ### 1. final关键字的基本概念 final是Java中一个非常重要的关键字,用于声明常量、阻止继承和重写,确保类、方法和变量的不可变性。具体来说,final关键字可以用来修饰类、方法和变量(包括成员变量和局部…...

ARM32开发--IIC软实现
知不足而奋进 望远山而前行 目录 文章目录 前言 开发流程 GD32F4软件I2C初始化 GD32F4软件I2C引脚功能 写操作 读操作 总结 前言 在嵌入式系统开发中,软件实现的I2C通信协议扮演着至关重要的角色。本文将深入探讨如何在GD32F4系列微控制器上实现软件I2C功能…...

在有向无环图(DAG)中实现拓扑排序与最短路径和最长路径算法
有向无环图(DAG)是一类非常重要的图结构,广泛应用于任务调度、数据依赖分析等领域。本文将介绍如何在DAG中实现拓扑排序、单源最短路径和单源最长路径算法,并提供完整的Java代码示例。 图结构定义 首先,我们定义一个…...

SQLServer按照年龄段进行分组查询数据
1.按照年龄段对数据进行分组, 将人群分为:青年,中年,老年三种类型,人群类型加上其他分组字段如:性别,进行多条件分组,统计各个年龄段多少人 Select case sex when 1 then ‘男’ when 2 then …...

开放式耳机哪个品牌质量比较好?2024高性价比机型推荐!
随着音乐技术的不断发展,开放式耳机已成为音乐发烧友们的另外一种选择。从最初的简单音质,到如今的高清解析,开放式耳机不断进化升级。音质纯净,佩戴舒适,无论是街头漫步还是家中放松时候,都能带给你身临其…...

Blender骨骼创建
骨骼系统 建立 使用Shift A添加骨骼或在添加|骨架中添加一段骨骼 骨骼的三种模式 -物体模式:做动画,摆人物pose时在该模式 -编辑模式:进行骨骼搭建(选择一段骨骼,然后按E挤出一段骨骼并进行调整) -姿…...

DevExpress WPF中文教程:Grid - 如何完成列和编辑器配置(设计时)?
DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…...

高考完的三个月想自学点编程,有没有什么建议
👆点击关注 获取更多编程干货👆 对于刚刚完成高考的学生来说,无论未来是否选择计算机科学作为专业方向,自学编程技能是一项非常有价值的投资,掌握编程知识能够帮助同学们为将来的学习和科研 实践奠定一个基础。 随着…...

运维开发(DevOps):加速软件交付的关键方法
1. 什么是运维开发 运维开发(DevOps)是将软件开发(Development)与信息技术运维(Operations)的流程整合在一起的实践方法。DevOps的目标是通过增强开发和运维团队之间的协作,提高软件产品的发布…...

Vue前端环境搭建:从四个方面、五个方面、六个方面和七个方面深度解析
Vue前端环境搭建:从四个方面、五个方面、六个方面和七个方面深度解析 在构建Vue.js项目时,搭建一个稳定且高效的前端环境至关重要。这不仅关乎项目的顺利推进,更直接影响开发者的效率和代码质量。本文将从四个方面、五个方面、六个方面和七个…...

农业领域科技查新点提炼方法附案例!
农业学科是人类通过改造和利用生物有机体(植物、动物、微生物等)及各种自然资源(光、热、水、土壤等)生产出人类需求的农产品的过程,人类在这一过程中所积累的科学原理、技术、工艺和技能,统称为农业科学技术,该领域具有研究范围广、综合性强…...

【Bazel入门与精通】 rules之属性
https://bazel.build/extending/rules?hlzh-cn#attributes Attributes An attribute is a rule argument. Attributes can provide specific values to a target’s implementation, or they can refer to other targets, creating a graph of dependencies. Rule-specifi…...

Elementor无需第三方插件实现高级下拉菜单/巨型菜单
使用新的嵌套功能创建美观的菜单和大型菜单。巨型菜单是具有复杂导航结构和独特设计的网站的理想选择。 Elementor-设置-特性-Menu启用 之后再去前端编辑器设计即可,就会有一个新的menu菜单模块了。 这个菜单的下拉则是通过Elementor直接来设计,也就以为…...

【数学】什么是傅里叶变换?什么是离散傅里叶变换?什么是拉普拉斯变换?
文章目录 什么是傅里叶变换?什么是离散傅里叶变换?什么是拉普拉斯变换?背景公式示例题目详细讲解Python代码求解实际生活中的例子 什么是线性时不变系统线性性(Linearity)时不变性(Time-Invariance…...

opencv安装笔记 各种平台
目录 python安装opencv-python c 麒麟arm系统安装和用法 python安装opencv-python pypi上搜索 Search results PyPI 现在安装是一个版本,大于3.6都可以安装 c 麒麟arm系统安装和用法 参考: ffmpeg rknn麒麟系统 安装 opencv_ffmpeg4 解码示例-CSDN…...

前端开发中的热更新原理
一、什么是热更新 热更新(Hot Module Replacement,HMR)是一种在前端开发中极为重要的技术。它允许开发者在不重新加载整个页面的情况下,实时更新应用程序中的某些模块。简单来说,热更新能让你在开发过程中即时看到代码…...

unix环境高级编程第2版:深入探索UNIX编程的奥秘
unix环境高级编程第2版:深入探索UNIX编程的奥秘 在数字世界的浩瀚海洋中,UNIX环境以其稳定、高效和灵活的特性,一直备受程序员们的青睐。而《unix环境高级编程第2版》这本书,无疑是探索UNIX编程奥秘的绝佳指南。接下来࿰…...

力扣42 接雨水
听说字节每人都会接雨水,我也要会哈哈哈 数据结构:数组 算法:核心是计算这一列接到多少雨水,它取决于它左边的最大值和右边的最大值,如下图第三根柱子能接到的雨水应该是第一根柱子高度和第五根柱子高度的最小值减去第…...

【代码随想录】【算法训练营】【第35天】[134]加油站 [135]分发糖果 [860]柠檬水找零 [406]根据身高重建队列
前言 思路及算法思维,指路 代码随想录。 题目来自 LeetCode。 day 35,连休两天~ 题目详情 [134] 加油站 题目描述 134 加油站 解题思路 前提:数组 思路:全局贪心算法:最小累加剩余汽油为负数,说明…...

Talk|新加坡国立大学贾鑫宇:适用于高自由度机器人的运动控制器
本期为TechBeat人工智能社区第600期线上Talk。 北京时间6月13日(周四)20:00,新加坡国立大学博士生—贾鑫宇的Talk已经准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “适用于高自由度机器人的运动控制器”,向大家系统地介绍了如何通…...

【npm】console工具(含胶囊,表格,gif图片)
这是一款控制台花样输出工具 相对丰富的输出方式 文本输出属性值输出胶囊样式输出表格输出图片输出(含动图) 安装 npm install v_aot引用 import v_aot from "v_aot";字段说明 字段类型属性字符串值字符串类型default 、 primary 、 suc…...