代码的工厂模式
概念:
代码的工厂模式是一种设计模式,用于创建对象实例而无需直接调用构造函数。它提供了一种更加灵活和可维护的方式来创建对象,尤其是在需要根据不同情况创建不同类型的对象时非常有用。工厂模式隐藏了对象的创建细节,使代码更加模块化和可扩展。
包括的关键元素:
-
工厂方法(Factory Method):这是一个方法或函数,负责创建对象实例。工厂方法通常接受一些参数,根据这些参数来确定应该创建哪种类型的对象。
-
产品(Product):产品是工厂方法创建的对象实例。产品通常是某个类的实例。
-
具体工厂(Concrete Factory):具体工厂是实际执行对象创建的类或函数。每个具体工厂通常负责创建特定类型的产品。
-
具体产品(Concrete Product):具体产品是由具体工厂创建的对象实例,它们是产品的具体实现。
工厂模式的主要优点:
-
封装对象创建过程:工厂模式将对象的创建逻辑封装在一个函数或类中,使客户端代码无需关心对象的具体创建方式。这可以减少代码的重复性,提高代码的可维护性和可读性。
-
灵活性:通过工厂模式,可以轻松地更改对象的创建方式,例如切换到不同的实现类或版本,而无需修改大量客户端代码。
-
解耦合:工厂模式有助于减少类之间的直接依赖关系。客户端代码不需要了解对象的具体类,只需与工厂接口或函数交互。这降低了耦合度,使系统更容易维护和扩展。
-
单一职责原则:工厂模式有助于遵循单一职责原则,因为它将对象的创建职责从客户端代码中分离出来,并将其委托给专门的工厂类或函数。
-
代码组织:工厂模式可以帮助组织代码,将对象创建逻辑集中在一个地方,使代码更加结构化和清晰。
-
测试和调试:工厂模式使得在单元测试中更容易替换模拟对象,从而更容易进行单元测试和调试。
总之,工厂模式是一种设计模式,有助于提高代码的可维护性、可扩展性和可测试性,同时降低了代码的耦合度,是面向对象编程中常用的一种设计方法之一。
代码案例:
源代码:
#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
函数来创建不同类型的动物对象,然后调用它们的吃和打方法。这样就实现了工厂模式,使得创建和使用不同类型的动物对象更加灵活和可维护。
如何理解这个模式的关键点:
-
抽象对象类型:在代码中,抽象对象类型是
struct Animal
,它定义了动物对象的通用属性和行为。这个抽象类型充当了工厂模式中的产品。 -
具体对象类型:不同种类的动物(狗、猫、人)被表示为具体对象类型,每个具体对象类型都有不同的实现,包括吃和打两个行为。这些具体对象类型充当了工厂模式中的具体产品。
-
工厂函数:
createAnimal
函数是工厂函数,它接受不同的参数(吃和打的函数指针)来创建不同类型的动物对象。这个工厂函数充当了工厂模式中的工厂,它负责创建具体产品。 -
客户端代码:在
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;
}
相关文章:
代码的工厂模式
概念: 代码的工厂模式是一种设计模式,用于创建对象实例而无需直接调用构造函数。它提供了一种更加灵活和可维护的方式来创建对象,尤其是在需要根据不同情况创建不同类型的对象时非常有用。工厂模式隐藏了对象的创建细节,使代码更…...

UE5.1编辑器拓展【一、脚本化资产行为,通知,弹窗,高效复制多个同样的资产】
目录 插件制作 添加新的类:AssetActionUtility 添加新的模块:EditorScriptingUtilities 路径了解 添加debug的头文件 代码【debug.h】内涵注释: 写函数 .h文件 .cpp文件 插件制作 首先第一步是做一个插件:…...

mac openssl 版本到底怎么回事 已解决
在mac 安装node多版本的时候,有可能把原有的 openssl1.1 版本 直接要再一次升级了,无奈的 php环境 编译器是 openssl 1.1 还是 3.0 ,今天来个底朝天的找问题。 brew search openssl 有安装 三个版本。 但是错误提示 是第二个版本。 brew …...
AWS】在EC2上创建root用户,并使用root用户登录
最近有项目需要使用AWS的EC2服务器; 在创建服务器实例之后发现,没有root用户,仔细阅读AWS EC2文档,发现默认是ec2-user用户; 那我们需要创建一个root用户 1.创建 root 用户 注意:必须要要在ec2-user用户下…...
9月24日回顾
1.微程序控制器的组成:指令译码器、微地址寄存器(输出和暂存控制信息),时序电路、最核心的部件是控制存储器(只读ROM组成)—用来存储微指令 2.突发读写:比如说突发地址为8,那么只需…...

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

防火墙基础之H3C防火墙和三层交换机链路聚合的配置
H3C防火墙和三层交换机链路聚合的配置 原理概述: 防火墙(英语:Firewall)技术是通过有机结合各类用于安全管理与筛选的软件和硬件设备,帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障,以保…...
管理类联考——数学——汇总篇——知识点突破——算数——记忆
文章目录 整体利用目录大纲/记忆宫殿目录大纲记忆宫殿 局部用各种方法数字编码法常见整除特点 歌决记忆法谐音记忆法理解记忆法比较记忆法转图像记忆法可视化法 整体利用目录大纲/记忆宫殿 目录大纲 记忆宫殿 局部用各种方法 学习记忆——数学篇——汇总——顺口溜记忆法谐…...

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

vue3简易文字验证码
大神勿喷,简易版本,demo中可以用一下。 需要几个文字自己codelen 赋值 灵活点直接父组件传过去,可以自己改造 首先创建一个生成数字的js **mathcode.js**function MathCode(num){let str "寻寻觅觅冷冷清清凄凄惨惨戚戚乍暖还寒时候…...
Java 23种设计模式分类概括以及应用介绍
话不多说进入正题~ 创建型模式:5种 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供全局访问点,它的主要目的是限制类的实例化并确保所有代码都共享相同的实例。 – 应用:Runtime类、数据库连…...
运筹优化算法常用求解器汇总
运筹学从形成到发展,在此过程中积累的大量理论和方法在国防、能源、制造、交通、金融、通信等各个领域发挥着越来越重要的作用。我们在生产生活中遇到的很多实际问题,都可以通过运筹学所涉及的优化方法对其进行数学建模,表示为数学问题&#…...

字符串函数(一)
✨博客主页:小钱编程成长记 🎈博客专栏:进阶C语言 字符串函数(一) 0.前言1.求字符串长度的函数1.1 strlen(字符串长度) 2.长度不受限制的字符串函数2.1 strcpy(字符串拷贝࿰…...

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的互动方式对用户进行分组的任务。它有助于找到保留用户,找到营销活动的用户群,并解决许多其他需要基于相似特征搜索用户的业务问题。这篇文章中,将带你完成使用Python进行机器学习的App用户细分任务。 App用户细…...
博弈论——伯特兰德寡头模型(Bertrand Model)
伯特兰德寡头模型(Bertrand Model) 0 引言 在前面几篇文章中,我们介绍了古诺模型(Cournot duopoly model)和斯塔克尔伯格模型(Stackelberg model) 博弈论——连续产量古诺模型(Cournot duopoly model) 博弈论——斯塔克尔伯格模型(Stackelberg model) 这两个模型…...
第一百六十回 SliverPadding组件
文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了SliverAppBar组件相关的内容,本章回中将介绍 SliverPadding组件.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在本章回中介绍的SliverPadding组件类似Pading组件,它主要用…...

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

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也可以...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...