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

代码的工厂模式

概念:

代码的工厂模式是一种设计模式,用于创建对象实例而无需直接调用构造函数。它提供了一种更加灵活和可维护的方式来创建对象,尤其是在需要根据不同情况创建不同类型的对象时非常有用。工厂模式隐藏了对象的创建细节,使代码更加模块化和可扩展。

 包括的关键元素:

  1. 工厂方法(Factory Method):这是一个方法或函数,负责创建对象实例。工厂方法通常接受一些参数,根据这些参数来确定应该创建哪种类型的对象。

  2. 产品(Product):产品是工厂方法创建的对象实例。产品通常是某个类的实例。

  3. 具体工厂(Concrete Factory):具体工厂是实际执行对象创建的类或函数。每个具体工厂通常负责创建特定类型的产品。

  4. 具体产品(Concrete Product):具体产品是由具体工厂创建的对象实例,它们是产品的具体实现。

 工厂模式的主要优点:

  1. 封装对象创建过程:工厂模式将对象的创建逻辑封装在一个函数或类中,使客户端代码无需关心对象的具体创建方式。这可以减少代码的重复性,提高代码的可维护性和可读性。

  2. 灵活性:通过工厂模式,可以轻松地更改对象的创建方式,例如切换到不同的实现类或版本,而无需修改大量客户端代码。

  3. 解耦合:工厂模式有助于减少类之间的直接依赖关系。客户端代码不需要了解对象的具体类,只需与工厂接口或函数交互。这降低了耦合度,使系统更容易维护和扩展。

  4. 单一职责原则:工厂模式有助于遵循单一职责原则,因为它将对象的创建职责从客户端代码中分离出来,并将其委托给专门的工厂类或函数。

  5. 代码组织:工厂模式可以帮助组织代码,将对象创建逻辑集中在一个地方,使代码更加结构化和清晰。

  6. 测试和调试:工厂模式使得在单元测试中更容易替换模拟对象,从而更容易进行单元测试和调试。

总之,工厂模式是一种设计模式,有助于提高代码的可维护性、可扩展性和可测试性,同时降低了代码的耦合度,是面向对象编程中常用的一种设计方法之一。

 

代码案例: 

 源代码:

#include <stdio.h>struct Animal
{char name[128];int age;int sex;int others;void (*peat)();void (*pbeat)();void (*test)();
};void dogEat()
{printf("狗吃屎\n");
}
void catEat()
{printf("猫吃鱼\n");
}
void personEat()
{printf("人吃米\n");
}
/
void dogBeat()
{printf("狗咬你\n");
}
void catBeat()
{printf("猫咬你\n");
}
void personBeat()
{printf("人打你\n");
}
int main()
{struct Animal dog = {.peat = dogEat,.pbeat = dogBeat,};struct Animal cat = {.peat = catEat,.pbeat = catBeat,};struct Animal person = {.peat = personEat,.pbeat = personBeat,};dog.peat();cat.peat();person.peat();dog.pbeat();cat.pbeat();person.pbeat();return 0;
}

工厂模式之后:

自行分开成一个个子文件

#include <stdio.h>// 定义动物结构体
struct Animal
{char name[128];int age;int sex;int others;void (*eat)();void (*beat)();
};// 定义不同类型的吃函数
void dogEat()
{printf("狗吃屎\n");
}void catEat()
{printf("猫吃鱼\n");
}void personEat()
{printf("人吃米\n");
}// 定义不同类型的打函数
void dogBeat()
{printf("狗咬你\n");
}void catBeat()
{printf("猫咬你\n");
}void personBeat()
{printf("人打你\n");
}// 创建动物工厂函数
struct Animal createAnimal(void (*eatFunc)(), void (*beatFunc)())
{struct Animal animal;animal.eat = eatFunc;animal.beat = beatFunc;return animal;
}int main()
{// 使用工厂函数创建不同类型的动物对象struct Animal dog = createAnimal(dogEat, dogBeat);struct Animal cat = createAnimal(catEat, catBeat);struct Animal person = createAnimal(personEat, personBeat);// 调用动物对象的方法dog.eat();cat.eat();person.eat();dog.beat();cat.beat();person.beat();return 0;
}

在上面的代码中,我们创建了一个createAnimal函数,它接受两个函数指针作为参数,并返回一个初始化好的动物对象。然后,在main函数中,我们使用createAnimal函数来创建不同类型的动物对象,然后调用它们的吃和打方法。这样就实现了工厂模式,使得创建和使用不同类型的动物对象更加灵活和可维护。

如何理解这个模式的关键点:

  1. 抽象对象类型:在代码中,抽象对象类型是struct Animal,它定义了动物对象的通用属性和行为。这个抽象类型充当了工厂模式中的产品。

  2. 具体对象类型:不同种类的动物(狗、猫、人)被表示为具体对象类型,每个具体对象类型都有不同的实现,包括吃和打两个行为。这些具体对象类型充当了工厂模式中的具体产品。

  3. 工厂函数createAnimal函数是工厂函数,它接受不同的参数(吃和打的函数指针)来创建不同类型的动物对象。这个工厂函数充当了工厂模式中的工厂,它负责创建具体产品。

  4. 客户端代码:在main函数中,客户端代码使用工厂函数来创建不同类型的动物对象,而不需要知道如何构造这些对象的细节。客户端只关心如何使用这些对象,而不关心它们的创建过程。

 用链表写法太麻烦,也发出来吧。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>// 定义动物结构体
struct Animal
{char name[128];       // 动物的名字void (*peat)();       // 吃的行为函数指针void (*pbeat)();      // 攻击的行为函数指针struct Animal *next;  // 指向下一个动物的指针
};// dog
void dogEat()
{printf("狗吃屎\n");
}
void dogBeat()
{printf("狗咬你\n");
}
struct Animal dog = {.name = "Pike",.peat = dogEat,.pbeat = dogBeat,.next = NULL
};// cat
void catEat()
{printf("猫吃鱼\n");
}
void catBeat()
{printf("猫咬你\n");
}
struct Animal cat = {.name = "Tom",.peat = catEat,.pbeat = catBeat,.next = NULL
};// person
void personEat()
{printf("人吃米\n");
}
void personBeat()
{printf("人打你\n");
}
struct Animal person = {.name = "Lihua",.peat = personEat,.pbeat = personBeat,.next = NULL
};// 向链表中添加动物
struct Animal *putAnimal(struct Animal *phead, struct Animal *animal)
{if (phead == NULL){phead = animal;}else{animal->next = phead;phead = animal;}return phead;
}// 根据名字查找动物
struct Animal *findName(char *str, struct Animal *phead)
{struct Animal *tmp = phead;if (phead == NULL){return NULL;}else{while (tmp != NULL){if (strcmp(tmp->name, str) == 0){return tmp;}tmp = tmp->next;}}return NULL;
}int main()
{char buf[128] = {'\0'};struct Animal *phead = NULL;struct Animal *ptmp;// 向链表中添加动物phead = putAnimal(phead, &dog);phead = putAnimal(phead, &cat);phead = putAnimal(phead, &person);while (1){printf("请输入:Pike、Tom、Lihua\n");scanf("%s", buf);struct Animal *ptmp = findName(buf, phead);if (ptmp != NULL){printf("姓名:%s\n", ptmp->name);ptmp->peat();ptmp->pbeat();}memset(buf, '\0', sizeof(buf));}return 0;
}

 

 

相关文章:

代码的工厂模式

概念&#xff1a; 代码的工厂模式是一种设计模式&#xff0c;用于创建对象实例而无需直接调用构造函数。它提供了一种更加灵活和可维护的方式来创建对象&#xff0c;尤其是在需要根据不同情况创建不同类型的对象时非常有用。工厂模式隐藏了对象的创建细节&#xff0c;使代码更…...

UE5.1编辑器拓展【一、脚本化资产行为,通知,弹窗,高效复制多个同样的资产】

目录​​​​​​​ 插件制作 添加新的类&#xff1a;AssetActionUtility 添加新的模块&#xff1a;EditorScriptingUtilities 路径了解 添加debug的头文件 代码【debug.h】内涵注释&#xff1a; 写函数 .h文件 .cpp文件 插件制作 首先第一步是做一个插件&#xff1a…...

mac openssl 版本到底怎么回事 已解决

在mac 安装node多版本的时候&#xff0c;有可能把原有的 openssl1.1 版本 直接要再一次升级了&#xff0c;无奈的 php环境 编译器是 openssl 1.1 还是 3.0 &#xff0c;今天来个底朝天的找问题。 brew search openssl 有安装 三个版本。 但是错误提示 是第二个版本。 brew …...

AWS】在EC2上创建root用户,并使用root用户登录

最近有项目需要使用AWS的EC2服务器&#xff1b; 在创建服务器实例之后发现&#xff0c;没有root用户&#xff0c;仔细阅读AWS EC2文档&#xff0c;发现默认是ec2-user用户&#xff1b; 那我们需要创建一个root用户 1.创建 root 用户 注意&#xff1a;必须要要在ec2-user用户下…...

9月24日回顾

1.微程序控制器的组成&#xff1a;指令译码器、微地址寄存器&#xff08;输出和暂存控制信息&#xff09;&#xff0c;时序电路、最核心的部件是控制存储器&#xff08;只读ROM组成&#xff09;—用来存储微指令 2.突发读写&#xff1a;比如说突发地址为8&#xff0c;那么只需…...

Spring注册Bean系列--方法1:@Component

原文网址&#xff1a;Spring注册Bean系列--方法1&#xff1a;Component_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring注册Bean的方法&#xff1a;Component。 注册Bean的方法我写了一个系列&#xff0c;见&#xff1a;Spring注册Bean(提供Bean)系列--方法大全_IT利刃出鞘…...

防火墙基础之H3C防火墙和三层交换机链路聚合的配置

H3C防火墙和三层交换机链路聚合的配置 原理概述&#xff1a; 防火墙&#xff08;英语&#xff1a;Firewall&#xff09;技术是通过有机结合各类用于安全管理​与筛选的软件和硬件​设备&#xff0c;帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保…...

管理类联考——数学——汇总篇——知识点突破——算数——记忆

文章目录 整体利用目录大纲/记忆宫殿目录大纲记忆宫殿 局部用各种方法数字编码法常见整除特点 歌决记忆法谐音记忆法理解记忆法比较记忆法转图像记忆法可视化法 整体利用目录大纲/记忆宫殿 目录大纲 记忆宫殿 局部用各种方法 学习记忆——数学篇——汇总——顺口溜记忆法谐…...

leetCode 455.分发饼干 贪心算法

455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&…...

vue3简易文字验证码

大神勿喷&#xff0c;简易版本&#xff0c;demo中可以用一下。 需要几个文字自己codelen 赋值 灵活点直接父组件传过去&#xff0c;可以自己改造 首先创建一个生成数字的js **mathcode.js**function MathCode(num){let str "寻寻觅觅冷冷清清凄凄惨惨戚戚乍暖还寒时候…...

Java 23种设计模式分类概括以及应用介绍

话不多说进入正题~ 创建型模式&#xff1a;5种 单例模式&#xff08;Singleton Pattern&#xff09; 确保一个类只有一个实例&#xff0c;并提供全局访问点&#xff0c;它的主要目的是限制类的实例化并确保所有代码都共享相同的实例。 – 应用&#xff1a;Runtime类、数据库连…...

运筹优化算法常用求解器汇总

运筹学从形成到发展&#xff0c;在此过程中积累的大量理论和方法在国防、能源、制造、交通、金融、通信等各个领域发挥着越来越重要的作用。我们在生产生活中遇到的很多实际问题&#xff0c;都可以通过运筹学所涉及的优化方法对其进行数学建模&#xff0c;表示为数学问题&#…...

字符串函数(一)

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 字符串函数&#xff08;一&#xff09; 0.前言1.求字符串长度的函数1.1 strlen&#xff08;字符串长度&#xff09; 2.长度不受限制的字符串函数2.1 strcpy&#xff08;字符串拷贝&#xff0…...

Ubuntu 安装 Docker 的详细步骤

文章目录 简介1.更新2.安装必要的软件包2.1 基于阿里源 3.验证 Docker 安装是否成功4.安装后的一些常规设置及常用的命令4.1 启动 Docker4.2 Docker 在系统启动时自动运行4.3 运行一个 Hello World 镜像4.4 查看docker运行状态 欢迎来到这篇关于在 Ubuntu 上安装 Docker 的教程…...

使用Python进行App用户细分

App用户细分是根据用户与App的互动方式对用户进行分组的任务。它有助于找到保留用户&#xff0c;找到营销活动的用户群&#xff0c;并解决许多其他需要基于相似特征搜索用户的业务问题。这篇文章中&#xff0c;将带你完成使用Python进行机器学习的App用户细分任务。 App用户细…...

博弈论——伯特兰德寡头模型(Bertrand Model)

伯特兰德寡头模型(Bertrand Model) 0 引言 在前面几篇文章中&#xff0c;我们介绍了古诺模型(Cournot duopoly model)和斯塔克尔伯格模型(Stackelberg model) 博弈论——连续产量古诺模型(Cournot duopoly model) 博弈论——斯塔克尔伯格模型(Stackelberg model) 这两个模型…...

第一百六十回 SliverPadding组件

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了SliverAppBar组件相关的内容&#xff0c;本章回中将介绍 SliverPadding组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在本章回中介绍的SliverPadding组件类似Pading组件&#xff0c;它主要用…...

Mapfree智驾方案,怎样实现成本可控?

整理|睿思 编辑|祥威 编者注&#xff1a;本文是HiEV出品的系列直播「智驾地图之变」第二期问答环节内容整理。 元戎启行副总裁刘轩与连线嘉宾奥维咨询董事合伙人张君毅、北汽研究总院智能网联中心专业总师林大洋、主持嘉宾周琳展开深度交流&#xff0c;并进行了答疑。 本期元…...

javascript: Bubble Sort

// Sorting Algorithms int JavaScript /** * file Sort.js * 1. Bubble Sort冒泡排序法 */ function BubbleSort(arry, nszie) {var i, j, temp;var swapped;for (i 0; i < nszie - 1; i){swapped false;for (j 0; j < nszie - i - 1; j){if (arry[j] > arry[j …...

DM数据库根据rowid删除重复的记录

oracle中rowid的用法-CSDN博客 delete from stu a where rowid not in (select max(b.rowid) from stu b where a.nob.no and a.name b.name and a.sex b.sex); //这里max使用min也可以...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

STM32标准库-ADC数模转换器

文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”&#xff1a;输入模块&#xff08;GPIO、温度、V_REFINT&#xff09;1.4.2 信号 “调度站”&#xff1a;多路开关1.4.3 信号 “加工厂”&#xff1a;ADC 转换器&#xff08;规则组 注入…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...