工厂模式应用实例

引言

设计模式概念

设计模式(Design Pattern)的官方概念可以表述为:在软件设计中,设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它是针对特定问题或特定场景的解决方案,是一种经过实践验证的最佳实践。设计模式主要用于解决软件设计中的各种问题,例如代码重复、性能问题、可维护性和可扩展性等。使用设计模式可以创建出可重用的解决方案,使代码更加清晰易懂、易维护和易扩展。设计模式不是语言特性或库,而是一种思想、一种方法论,它可以被应用于各种编程语言和框架中。学习设计模式可以提高设计能力和编程水平。

工厂模式概念:

工厂模式(Factory Pattern)是 最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的  最佳  方式。

工厂模式提供了一种创建对象的方式,而 无需指定要创建的具体类。

工厂模式属于创建型模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离。

特点:

创建对象时,- 会对客户端暴露创建逻辑,并且是 通过 使用同一接口(API) 来指向新创建的对象

工厂模式的优势

工厂模式的优势主要体现在以下几个方面:

  1. 解耦:工厂模式将对象的创建与使用分离,使得代码结构更加清晰。当需要创建新的对象时,无需修改使用对象的代码,只需修改工厂类即可,这大大降低了代码的耦合度。

  2. 封装性:工厂模式隐藏了对象的创建细节,使用者只需知道所需对象的接口,而无需知道具体的创建过程。这增强了系统的封装性,使得代码更加易于理解和维护。

  3. 可扩展性:当需要添加新的产品时,只需在工厂类中增加一个新的产品创建方法,并修改返回类型或添加新的工厂子类,而无需修改使用对象的代码。这使得系统更加易于扩展。

  4. 灵活性:工厂模式可以根据不同的条件创建不同的对象实例。例如,可以通过配置文件或参数化工厂方法来创建不同的对象,这使得系统更加灵活。

  5. 符合开闭原则:工厂模式符合开闭原则,即对于扩展是开放的,对于修改是封闭的。当需要添加新的产品时,只需扩展工厂类而无需修改已有代码。

  6. 简化代码:通过工厂模式,可以将复杂的创建过程封装在工厂类中,从而简化使用对象的代码。同时,工厂模式还可以减少代码中的重复部分,提高代码的可重用性。

  7. 便于测试:工厂模式可以将创建对象的代码与使用对象的代码分离,这使得在测试过程中可以更容易地模拟或替换对象实例,从而便于进行单元测试或集成测试。

总之,工厂模式通过解耦、封装、可扩展性、灵活性、开闭原则、简化代码和便于测试等优势,使得系统更加易于理解维护扩展测试

工厂模式实现

(以下代码为例):

混乱的单文件代码


#include <stdio.h>//  结构体实现类 -- 抽象
struct Animal
{//  成员属性char name[128];int age;int sex;// 成员方法// 注意这里是函数指针, if 不加上(), 就变成了返回值是 void*void (*peat)();void (*pbeat)();
};void dogEat()
{puts("狗吃屎");
}void catEat()
{puts("猫吃鱼");
}void personEat()
{puts("人吃米");
}void dogBeat()
{puts("d四你");
}void catBeat()
{puts("c四你");
}void personBeat()
{puts("p四你");
}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;
}

工厂模式设计图: 


封装各个函数 


记得把 main 函数需要 用到 .c(源文件)里面的函数,在需要包含的.h(头文件)中声明,不然 在main里面不能调用到


====================================
以下是全部文件

main.c

#include <string.h>#include "animal.h"// 链表的查找
struct Animal*findUtilByName(char *str,struct Animal*phead)
{struct Animal* p = phead;if(NULL == phead){puts("空链表");return NULL;}else{while(NULL != p){if(strcmp(p->name,str) == 0){return  p;}p = p->next;}}return NULL;}int main()
{char buf[128] ={'\0'};struct Animal* phead = NULL;struct Animal* ptmp;//将我们需要的三种对象加入到链表中 phead = putCatToLink(phead);phead = putdogToLink(phead);phead = putpersonToLink(phead);while (1) // 这就算我们需要实现的业务{puts("请选择你需要的对象,包括:Tom, huang, likui");scanf("%s",buf);ptmp = findUtilByName(buf,phead);if(NULL != ptmp){ptmp->peat();ptmp->pbeat();}memset(buf,'\0',sizeof(buf));}return 0;
}

==============================================


animal.h

#ifndef __ANIMAL_H_
#define __ANIMAL_H_#include <stdio.h>struct Animal
{//  成员属性char name[128];int age;int sex;// 成员方法// 注意这里是函数指针, if 不加上(), 就变成了返回值是 void*void (*peat)();void (*pbeat)();struct Animal * next; //我们使用链表来遍历所有对象
};struct  Animal *putpersonToLink(struct  Animal *phead);
struct  Animal * putdogToLink(struct  Animal *phead);
struct  Animal * putCatToLink(struct  Animal *phead);#endif


==============================================


cat.c

#include "animal.h"void catEat()
{puts("猫吃鱼");
}void catBeat()
{puts("挠四你");
}
// 这里面的赋值 用到的函数 需要在前面先定义, 注意位置不能错
struct Animal cat = {.name = "Tom",.peat = catEat,.pbeat = catBeat};// 头插法  -- 向链表中添加猫对象struct  Animal * putCatToLink(struct  Animal *phead)
{
//    if(NULL == phead)
//    {
//     phead = &cat; 
//    }
//    else
//    {
//     cat.next = phead;
//     phead = &cat;
//    }if(NULL != phead)    //if链表里面已经有数据的话cat.next = phead; // 把cat插入头节点的后面
phead = &cat; //空链表 cat 就作为头 | 非空 cat 插入到头节点后面之后也会成为新的头return phead;
}

==============================

dog.c

#include "animal.h"void dogEat()
{puts("狗吃屎");
}void dogBeat()
{puts("咬四你");
}
struct Animal dog = {.name = "huang",.peat = dogEat,.pbeat = dogBeat};// 头插法  -- 向链表中添加猫对象struct  Animal * putdogToLink(struct  Animal *phead)
{if(NULL != phead)    //if链表里面已经有数据的话dog.next = phead; // 把dog插入头节点的后面
phead = &dog; //空链表 dog 就作为头 | 非空 dog 插入到头节点后面之后也会成为新的头return phead;
}


person.c

#include "animal.h"
#include <stdio.h>void personEat()
{puts("人吃米");
}void personBeat()
{puts("骂四你");
}struct Animal person = {.name = "likui",.peat = personEat,.pbeat = personBeat};// 头插法  -- 向链表中添加猫对象struct  Animal *putpersonToLink(struct  Animal *phead)
{if(NULL != phead)    //if链表里面已经有数据的话person.next = phead; // 把person插入头节点的后面
phead = &person; //空链表 person 就作为头 | 非空 person 插入到头节点后面之后也会成为新的头return phead;
}

// if 我们需要 扩展功能 --> 比如添加对象

这时候工厂 模式优势就体现出来了

常见问题:


fish.c:22:18: error: conflicting types for ‘putfishToLink’; have ‘struct Animal *(struct Animal *)’
   22 | struct  Animal * putfishToLink(struct  Animal *phead)  --> 这种报错通常是 源文件改了,但是头文件没有改


==========================


扩展 

 添加 fish.c
#include "animal.h"void fishEat()
{puts("大鱼小鱼");
}void fishBeat()
{puts("吐泡泡");
}
struct Animal fish = {.name = "dayu",.peat = fishEat,.pbeat = fishBeat};// 头插法  -- 向链表中添加猫对象struct  Animal * putfishToLink(struct  Animal *phead)
{if(NULL != phead)    //if链表里面已经有数据的话fish.next = phead; // 把fish插入头节点的后面
phead = &fish; //空链表 fish 就作为头 | 非空 fish 插入到头节点后面之后也会成为新的头return phead;
}

//然后我们只需要修改.h 头文件中包含的函数, 和main里面的逻辑
// 我们发现添加一次动物我们就需要去选项输出一次名字不太友好,那么我们可以优化遍历链表输出


新的main.c :
#include <string.h>#include "animal.h"// 链表的查找
struct Animal*findUtilByName(char *str,struct Animal*phead)
{struct Animal* p = phead;if(NULL == phead){puts("空链表");return NULL;}else{while(NULL != p){if(strcmp(p->name,str) == 0){return  p;}p = p->next;}}return NULL;}void getAllName(struct Animal*phead){struct Animal* p = phead;if(NULL == phead){puts("空链表");}else{while(NULL != p){printf("%s ",p->name);p = p->next;}}}int main()
{char buf[128] ={'\0'};struct Animal* phead = NULL;struct Animal* ptmp;//将我们需要的三种对象加入到链表中 phead = putCatToLink(phead);phead = putdogToLink(phead);phead = putpersonToLink(phead);phead = putfishToLink(phead);while (1) // 这就算我们需要实现的业务{puts("请选择你需要的对象,包括:");getAllName(phead);scanf("%s",buf);ptmp = findUtilByName(buf,phead);if(NULL != ptmp){ptmp->peat();ptmp->pbeat();}memset(buf,'\0',sizeof(buf));}return 0;
}

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

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

相关文章

单元测试之TestNG知识点总结及代码示例

TestNG 是一个测试框架&#xff0c;用于自动化测试 Java 和 Scala 应用程序&#xff0c;它是 JUnit 和 NUnit 的一个强大替代品。TestNG 支持数据驱动测试、参数化测试、测试套件、依赖管理、多线程测试等特性。TestNG官网&#xff1a;TestNG Documentation 目录 1.TestNG 基…

虹科Pico汽车示波器 | 免拆诊断案例 | 2010款凯迪拉克SRX车发动机无法起动

故障现象 一辆2010款凯迪拉克SRX车&#xff0c;搭载LF1发动机&#xff0c;累计行驶里程约为14.3万km。该车因正时链条断裂导致气门顶弯&#xff0c;大修发动机后试车&#xff0c;起动机运转有力&#xff0c;但发动机没有着机迹象&#xff1b;多起动几次&#xff0c;火花塞会变…

网络编程:服务器模型-并发服务器-多进程

并发服务器概念&#xff1a; 并发服务器同一时刻可以处理多个客户机的请求 设计思路&#xff1a; 并发服务器是在循环服务器基础上优化过来的 &#xff08;1&#xff09;每连接一个客户机&#xff0c;服务器立马创建子进程或者子线程来跟新的客户机通信 &#xff08;accept之后…

QT--4

QT 使用定时器完成闹钟 #include "widget.h" #include "ui_widget.h"void Widget::timestart() {timer.start(1000); }void Widget::timeend() {timer.stop(); }Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(t…

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测 目录 分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现DBO-CNN-SVM蜣螂算法…

【卫星影像三维重建-全流程代码实现】点云Mesh重构

点云—>Mesh模型 1.介绍1.1 背景1.2 效果示意 2 算法实现2.1 依赖库2.2 实验数据2.3 代码实现2.4 实验效果 3.总结 1.介绍 1.1 背景 &#xff08;1&#xff09;本文主要内容是将三维点云&#xff08;离散的三维点&#xff09;进行表面重建生成Mesh网格&#xff0c;之前有篇…

Middle for Mac:简洁高效的文本编辑软件

追求简洁与高效&#xff1f;Middle for Mac将是您文本编辑的最佳选择。这款Mac平台上的文本编辑器&#xff0c;以其独特的魅力和实用的功能&#xff0c;赢得了众多用户的喜爱。 Middle注重用户体验&#xff0c;采用简洁直观的界面设计&#xff0c;让您能够迅速上手并享受高效的…

巩固学习6

正则表达式 又称规则表达式&#xff0c;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a到z之间的字母&#xff09;和特殊字符&#xff08;称为“元字符”&…

今天开发了一款软件,我竟然只用敲了一个字母(文末揭晓)

软件课题&#xff1a;Python实现打印100内数学试题软件及开发过程 一、需求管理&#xff1a; 1.实现语言&#xff1a;Python 2.打印纸张&#xff1a;A4 3.铺满整张纸 4.打包成exe 先看效果&#xff1a; 1. 2.电脑打印预览 3.打印到A4纸效果&#xff08;晚上拍的&#x…

【实践】使用vscode来debug go程序的尝鲜

配置 首先&#xff0c;当然得配置好vscode 的go环境&#xff0c; 装个go插件就基本满足了 配置 launch.json, 可以配置多个环境的程序启动参数&#xff08;很友好&#xff09; {"version": "0.2.0","configurations": [{"name": &…

享元模式详解

享元模式 1 概述 定义&#xff1a; ​ 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销&#xff0c;从而提高系统资源的利用率。 2 结构 享元&#xff08;Flyweight &#xff09;模式中存…

linux学习:视频输入+V4L2

目录 V4L2 视频采集流程 代码例子 核心命令字和结构体 VIDIOC_ENUM_FMT VIDIOC_G_FMT / VIDIOC_S_FMT / VIDIOC_TRY_FM VIDIOC_REQBUFS VIDIOC_QUERYBUF VIDIOC_QBUF /VIDIOC_DQBUF VIDIOC_STREAMON / VIDIOC_STREAMOFF V4L2 是 Linux 处理视频的最新标准代码模块&…

力扣HOT100 - 45. 跳跃游戏 II

解题思路&#xff1a; 贪心 class Solution {public int jump(int[] nums) {int end 0;int maxPosition 0;int steps 0;for (int i 0; i < nums.length - 1; i) {maxPosition Math.max(maxPosition, i nums[i]);if (i end) {end maxPosition;steps;}}return steps;…

Java | Leetcode Java题解之第86题分隔链表

题目&#xff1a; 题解&#xff1a; class Solution {public ListNode partition(ListNode head, int x) {ListNode small new ListNode(0);ListNode smallHead small;ListNode large new ListNode(0);ListNode largeHead large;while (head ! null) {if (head.val < x…

java sql中 大于 小于 大于等于 小于等于 代替符号

在写java时sql会经常会忘记大于小于号的表示方法导致无法运行&#xff0c;总结一下 第一种方法&#xff1a; < &#xff1a;< < &#xff1a; < &#xff1a;> &#xff1a; > sql如下&#xff1a; create_at > #{startTime} and create_at < #{end…

Linux系统编程:进程控制

1.进程创建 1.1 fork函数 fork&#xff08;&#xff09;通过复制调用进程来创建一个新进程。新进程称为子进程&#xff0c;是调用进程的精确副本 进程&#xff0c;但以下几点除外&#xff1a; 子进程有自己的PID&#xff0c;此PID与任何现有进程组的ID不匹配子进程的父进程ID…

【全开源】废品回收微信小程序基于FastAdmin+ThinkPHP+UniApp

介绍 一款基于FastAdminThinkPHPUniApp开发的废品回收系统&#xff0c;适用废品回收站、再生资源回收公司上门回收使用的小程序 功能特性 1、会员注册 支持小程序授权注册和手机号注册 2、回收品类 可设置回收品类&#xff0c;废纸、废金属、废玻璃、旧衣服等 3、今日指导价…

简单实现---基于STL的演讲比赛流程管理系统(C++实现)

前言 事先声明&#xff1a;本文章中编写的代码仅用于学习算法思想和编写基础形式使用&#xff0c;并未进行太多的代码优化&#xff0c;因此&#xff0c;若需要对代码进行优化以及异常处理的小伙伴们&#xff0c;可自行添加相关操作&#xff0c;谢谢&#xff01; 一、题…

jenkins使用gitLab(极狐)认证登陆

jenkins安装 GitLab Authentication插件 我因为java版本和最新GitLab Authentication 1.19版本不兼容&#xff0c;选择了本地安装 找个历史版本1.13版本&#xff0c;然后下载到电脑上 - 本地上传插件并安装 在极狐上创建一个应用 - 配置应用信息 应用名&#xff1a;jenkinsLo…

[Linux][网络][高级IO][一][五种IO模型][同步通信][异步通信][非阻塞IO]详细讲解

目录 0.预备知识 && 思考问题1.五种IO模型0.形象理解五种模型1.阻塞IO2.非阻塞IO3.信号驱动IO4.多路转接/多路复用5.异步IO 2.高级IO重要概念1.同步通信 vs 异步通信2.阻塞 vs 非阻塞 3.非阻塞IO1.fcntl()2.实现SetNonBlock 0.预备知识 && 思考问题 网络通信本…