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

学习设计模式《一》——简单工厂

一、基础概念

 1.1、接口

        简单的说:接口是【用来实现类的行为定义、约束类的行为】(即:定义可以做什么)接口可以包含【实例方法】、【属性】、【事件】、【索引器】或这四种成员类型的任意组合

       接口的优点:可以将外部调用和内部实现隔离开;只要接口不变,内部实现的变化就不会影响到外部应用,从而使系统更加灵活,具有更好的拓展性和可维护性

        何时选用接口?(通常情况下优先使用接口)。

        何时选用抽象类?(既要定义子类的行为、又要为子类提供公共的功能时选抽象类)。

接口 - 定义多种类型的行为 - C# | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/fundamentals/types/interfaces接口关键字 - C# reference | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/interface

 1.2、简单工厂

        工厂就是用来创造东西的(通常情况下工厂是用来创造接口对象的)  但是也可以用来创造抽象类,甚至是一个具体的类实例

        简单工厂方法的内部主要实现的功能是【选择合适的实现类】来创建实例对象,涉及到选择, 就需要选择的条件或参数(这些选择条件或参数可来源于客户端传入、配置文件传入或程序运行时的某个值传入) 这样要传入参数就会存在一个缺点【就是客户端必须要知道每个参数的含义(同时也需要理解每个参数对应的功能处理)】这样的话 就导致了在一定程度上给客户端暴露了内部的一些实现细节

简单工厂的命名:
        《类名称》:建议是【模块名称+Factory】(如接口名称是:ITestApi,则简单工厂类名称是:TestApiFactory);
        《方法名称》:建议是【Get+接口名称】、【Create+接口名称】或【Build+接口名称】  (如接口名称是:ITestApi,则简单工厂内对应的接口名称是:GetTestApi、CreateTestApi或BuildTestApi);

静态工厂:

        使用简单工厂的时候,通常不用创建简单工厂类的实例(没必要), 因此可以直接把简单工厂类实现为一个工具类(即:使用static修饰方法为静态的);而工厂的方法通常都是静态的,所以称其为静态工厂

简单工厂的优缺点
序号简单工厂优点简单工厂缺点
1帮助封装,让外部实现了真正的面向接口编程可能增加客户端的复杂度(即简单工厂是选择条件或参数来进行合适类对象的创建,对外会暴露细节,增加客户端使用难度)
2解耦,通过简单工厂,实现客户端与具体实现类的解耦不方便扩展子工厂

二、简单工厂示例

 2.1、常规接口使用方法

  1、先定义一个接口

/***
*	Title:"设计模式" 项目
*		主题:简单工厂
*	Description:
*	    基础概念:
*	        接口:(接口是【用来实现类的行为定义、约束类的行为】)
*	            1、接口里的所有方法都是【抽象方法】(注意:C#8.0以前方法只有定义没有实现; C# 8.0开始,接口可以定义其部分或全部成员的默认实现)
*	            2、接口里面的所有属性都是常量
*	            3、何时选用接口?【通常情况下优先使用接口】
*	            4、使用接口的好处【可以将外部调用和内部实现隔离开;只要接口不变,
*	                内部实现的变化就不会影响到外部应用,从而使系统更加灵活,具有更好的拓展性和可维护性】
*	            5、何时选用抽象类?【既要定义子类的行为、又要为子类提供公共的功能时选抽象类】
*		功能:
*		
*	Date:2025
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:***/namespace SimpleFactory
{/// <summary>/// 定义一个接口(接口是通用的、抽象的、非具体的功能,定义行为/// 【简单的说:就是可以做什么】)/// </summary>public interface ITestApi{/// <summary>/// 定义了一个传入字符串的测试打印方法/// </summary>/// <param name="info">需传入的参数</param>void TestPrint(string info);}
}

  2、实现接口的测试类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace SimpleFactory
{/// <summary>/// 实现接口的测试类/// </summary>internal class ImplTestApi : ITestApi{public void TestPrint(string info){if (string.IsNullOrEmpty(info)) { return; }string str = $"实现接口定义传递一个参数的打印方法,打印内容是:{info}";Console.WriteLine(str);}}//Class_end
}

  3、客户端调用

namespace SimpleFactory
{internal class Program{/// <summary>/// 客户端:测试使用ITestApi接口/// </summary>/// <param name="args"></param>static void Main(string[] args){Console.WriteLine("1-接口与实现类的示例");//仔细查看这里:我们只知到ITestApi接口,而不知道是哪个类实现了它,这样就得不到接口对象,无法使用接口,应该怎么办?ITestApi testApi=new ImplTestApi();testApi.TestPrint("你好,这是一个简单的测试");Console.ReadLine();}}//Class_end
}

  运行结果:

 2.2、简单工厂

1、再编写两个接口的实现类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace SimpleFactory
{/// <summary>/// 实现ITestApi接口的对象A/// </summary>internal class ImplA : ITestApi{public void TestPrint(string info){//具体的实现功能代码string str = $"我是对象【A】实现的打印逻辑,打印内容是:{info}";Console.WriteLine(str);}}//Class_end
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace SimpleFactory
{/// <summary>/// 实现ITestApi接口的对象B/// </summary>internal class ImplB : ITestApi{public void TestPrint(string info){//具体的实现功能代码if (info.Contains(',')){string[] tmpStr = info.Split(',');Console.WriteLine("我是对象【B】实现的打印逻辑,打印内容是:");foreach (string s in tmpStr){Console.WriteLine(s);}}}}//Class_end
}

 2、构建简单工厂

/***
*	Title:"设计模式" 项目
*		主题:简单工厂
*	Description:
*	    基础概念:
*	        工厂就是用来创造东西的(通常情况下工厂是用来创造接口对象的)
*	            但是也可以用来创造抽象类,甚至是一个具体的类实例
*	            
*	        《静态工厂》:使用简单工厂的时候,通常不用创建简单工厂类的实例(没必要),
*		              因此可以直接把简单工厂类实现为一个工具类(即:使用static修饰方法为静态的);
*		              而工厂的方法通常都是静态的,所以称其为静态工厂
*		    《万能工厂》:
*		        一个简单工厂可以包含很多构建东西的方法(这些方法可以创建不同的接口、抽象类或类示例)
*		        也就是说理论上一个简单工厂其实可以构建任何东西,因此又叫做万能工厂
*		        注意:虽然理论上简单工厂可以创建任何东西,但是实际使用中不建议简单工厂可创建对象的范围太大,
*		              建议是一个简单工厂控制在一个独立的模块内,这样使用起来才会职责清晰不混乱
*		            
*		    《简单工厂的命名》:
*		        《类名称》:建议是【模块名称+Factory】(如接口名称是:ITestApi,则简单工厂类名称是:TestApiFactory)
*		        《方法名称》:建议是【Get+接口名称】、【Create+接口名称】或【Build+接口名称】
*		        (如接口名称是:ITestApi,则简单工厂内对应的接口名称是:GetTestApi、CreateTestApi或BuildTestApi)
*		    
*		功能:
*		     简单工厂方法的内部主要实现的功能是【选择合适的实现类】来创建实例对象,涉及到选择,
*		     就需要选择的条件或参数(这些选择条件或参数可来源于客户端传入、配置文件传入或程序运行时的某个值传入)
*		     这样要传入参数就会存在一个缺点【就是客户端必须要知道每个参数的含义(同时也需要理解每个参数对应的功能处理)】这样的话
*		     就导致了在一定程度上给客户端暴露了内部的一些实现细节
*		     
*		     《优点》:
*		            1、帮助封装,让外部实现了真正的面向接口编程
*		            2、解耦,通过简单工厂,实现客户端与具体实现类的解耦
*		     《缺点》:
*		            1、可能增加客户端的复杂度(即简单工厂是选择条件或参数来进行合适类对象的创建,对外会暴露细节,增加客户端使用难度)
*		            2、不方便扩展子工厂
*	Date:2025
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:***/using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace SimpleFactory
{/// <summary>/// ITestApi接口的简单工厂(用于创建接口的实现对象)/// (解决:只知到ITestApi接口,而不知道是哪个类实现了它,这样就得不到接口对象,无法使用接口问题)/// </summary>internal class TestApiFactory{/// <summary>/// 构建ITestApi接口的实现类/// </summary>/// <param name="implObjNum">实现对象编号</param>/// <returns>返回创建好的ITestApi对象</returns>public static ITestApi BuildTestApi(int implObjNum){ITestApi testApi = new ImplTestApi();switch (implObjNum){case 0:testApi = new ImplTestApi();break;case 1:testApi = new ImplA();break;case 2:testApi = new ImplB();break;default:break;}return testApi;}}//Class_end
}

3、客户端调用

namespace SimpleFactory
{internal class Program{/// <summary>/// 客户端:测试使用ITestApi接口/// </summary>/// <param name="args"></param>static void Main(string[] args){Console.WriteLine("1-接口与实现类的示例");//仔细查看这里:我们只知到ITestApi接口,而不知道是哪个类实现了它,这样就得不到接口对象,无法使用接口,应该怎么办?ITestApi testApi=new ImplTestApi();testApi.TestPrint("你好,这是一个简单的测试");Console.WriteLine("\n2-学习设计模式——简单工厂");/**** 通过简单工厂来获取ITestApi接口对象* (这里客户端只知道通过简单工厂创建了一个接口的对象,面向接口编程:* 从客户端这里来看,它其实根本不知道具体的实现是什么,也不知道是如何实现的,* 它只知道通过工厂获得了一个接口对象,然后通过这个接口来获取想要的功能)* * 在这里通过简单工厂帮助我们真正的面向接口编程,* 上面的【接口与实现类的示例】做法,只用到了接口的多态功能;* 而最重要的【封装隔离性】并没有体现出来* ***/ITestApi testApi1 = TestApiFactory.BuildTestApi(0);testApi1.TestPrint("你好,这是一个简单的测试");testApi1=TestApiFactory.BuildTestApi(1);testApi1.TestPrint("你好,这是一个简单的测试");testApi1 = TestApiFactory.BuildTestApi(2);testApi1.TestPrint("你好,这是一个简单的测试");Console.ReadLine();}}//Class_end
}

 运行结果

工厂模型概述 - ADO.NET | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/framework/data/adonet/factory-model-overview 

三、项目源码工程

kafeiweimei/Learning_DesignPattern: 这是一个关于C#语言编写的基础设计模式项目工程,方便学习理解常见的26种设计模式https://github.com/kafeiweimei/Learning_DesignPattern

相关文章:

学习设计模式《一》——简单工厂

一、基础概念 1.1、接口 简单的说&#xff1a;接口是【用来实现类的行为定义、约束类的行为】&#xff08;即&#xff1a;定义可以做什么&#xff09;&#xff1b;接口可以包含【实例方法】、【属性】、【事件】、【索引器】或这四种成员类型的任意组合。 接口的优点&#xff1…...

python有序列表

您的代码整体结构良好&#xff0c;但存在一些关键错误和优化点。以下是对代码的详细评价及改进建议&#xff1a;---### 主要问题1. **add方法中的链表断裂问题**- **问题描述**&#xff1a;当向链表中间插入节点时&#xff0c;未正确设置新节点的next&#xff0c;导致后续节点丢…...

使用Lombok @Builder 收参报错提示没有无参构造方法的原因与解决办法

使用Lombok Builder 收参报错提示没有无参构造方法的原因与解决办法 类上加了Builder之后接口接收前端传来的参数报错&#xff1a;(no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) 1.解决办法…...

010数论——算法备赛

数论 模运算 一般求余都是对正整数的操作&#xff0c;如果对负数&#xff0c;不同编程语言结果可能不同。 C/javapythona>m,0<a%m<m-1 a<m,a%ma~5%32~-5%3 -21(-5)%(-3) -2~5%(-3)2-1正数&#xff1a;&#xff08;ab&#xff09;%m((a%m)(b%m))%m~正数&#xff…...

NAT、代理服务、内网穿透

NAT、代理服务、内网穿透 1、NAT1.1、NAT过程1.2、NAPT2、内网穿透3、内网打洞3、代理服务器3.1、正向代理3.2、反向代理1、NAT 1.1、NAT过程 之前我们讨论了IPv4协议中IP地址数量不充足的问题。NAT技术是当前解决IP地址不够用的主要手段,是路由器的一个重要功能。 NAT能够将…...

C# 点击导入,将需要的参数传递到弹窗的页面

点击导入按钮&#xff0c;获取本页面的datagridview标题的结构&#xff0c;并传递到导入界面。 新增一个datatable用于存储datagridview的caption和name&#xff0c;这里用的是devexpress组件中的gridview。 DataTable dt new DataTable(); DataColumn CAPTION …...

Linux 文件查找终极指南:find, locate, grep 等命令详解

在 Linux 系统管理和日常使用中,文件查找是一项不可或缺的基本技能。无论是寻找配置文件、查找日志文件中的特定错误,还是清理旧的临时文件,掌握高效的文件查找工具都能让你事半功倍。Linux 提供了多种强大的命令行工具来满足不同的查找需求。本文将详细介绍几个最常用、最强…...

嵌入式硬件常用总线接口知识体系总结和对比

0.前言 在嵌入式工程实现中,多多少少我们都使用过总线,各种各样的总线应用于不同场合,不同场景有不同的优势,但是我们在作为工程师过程中在如何选择项目合适的总线,根据什么来选?需要我们对项目全局和总线特征有所了解,本文目的就是对比多种总线的关键特征 我们在聊到…...

【unity实战】Unity动画层级(Animation Layer)的Sync同步和Timing定时参数使用介绍,同步动画层制作角色的受伤状态

文章目录 前言方案一&#xff1a;复制粘贴原有层级的状态机1、实现2、问题 方法二&#xff1a;勾选Sync同步动画层1、简单实现同步2、同步blend tree的问题3、动画状态的播放时长4、下层状态覆盖了上层状态 专栏推荐完结 前言 如何制作角色的受伤状态&#xff1f; 玩家角色在…...

Uniapp调用native.js使用经典蓝牙串口通讯方法及问题解决

本人尝试在uniapp环境下开发一款安卓应用&#xff0c;需要与使用经典蓝牙协议的设备进行串口通讯&#xff0c;而uniapp官方给出的蓝牙操作接口目前只支持BLE&#xff08;低功耗蓝牙&#xff09;&#xff0c;用该接口无法正常获取到我想要连接的设备。 通过大量搜索&#xff0c…...

C++23 新特性:行拼接前去除空白符 (P2223R2)

文章目录 1\. 什么是行拼接前去除空白符2\. 为什么需要这一特性3\. 示例代码输出结果 4\. 编译器支持5\. 优势与应用场景5.1 提高代码可读性5.2 减少潜在错误5.3 适用于多行字符串 6\. 其他相关特性7\. 总结 C 语言一直在不断进化&#xff0c;以满足现代软件开发的需求。C23 标…...

Windows 11设置开机自动运行 .jar 文件

Windows 11设置开机自动运行 .jar 文件 打开启动文件夹&#xff1a; 按下 Win R&#xff0c;输入 shell:startup&#xff0c;回车。 此路径为当前用户的启动文件夹&#xff1a; C:\Users\<用户名>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup创…...

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法】

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法 问题产生缘由感谢这位大佬提供的解决办法解决办法 问题产生缘由 通过Zadig给鼠标适配器安装USB GAMING MOUSE这个驱动后,鼠标动不了,无法恢复(重启电脑,卸载鼠标驱动再重装也不可以), 不过还好,我用的是笔记…...

GoogleCodeUtil.java

Google动态验证码实现 GoogleCodeUtil.java package zwf;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.SecureRandom;/** https://mvnrepository.com/artifact/commons-codec/…...

Maven 简介(图文)

Maven 简介 Maven 是一个Java 项目管理和构建的工具。可以定义项目结构、项目依赖&#xff0c;并使用统一的方式进行自动化构建&#xff0c;是Java 项目不可缺少的工具。 Maven 的作用 提供标准化的项目结构&#xff1a;以前不同的开发工具创建的项目结构是不一样的&#xf…...

JESD204B标准及其在高速AD采集系统中的应用详解

一、JESD204B协议的本质与核心价值 JESD204B是由JEDEC制定的第三代高速串行接口标准&#xff08;2011年发布&#xff09;&#xff0c;专为解决高速ADC/DAC与FPGA/ASIC间数据传输瓶颈而设计。其核心突破体现在&#xff1a; 速率革命性提升 支持每通道最高12.5Gbps&#xff08;通…...

天梯赛数据结构合集

1.集合操作&#xff1a;PTA | 程序设计类实验辅助教学平台 主要是注意set的取交集操作&#xff0c;AC代码&#xff1a; #include<bits/stdc.h> using namespace std; int n,m,k; set<int> a[60]; int main(){cin>>n;for(int i1;i<n;i){cin>>m;for…...

2025Github介绍与注册(有图片讲解,保姆级)

为什么要注册Github账号 利于团队协作&#xff0c;特别是打比赛的队友 版本控制强大&#xff0c;代码安全 开源项目多&#xff0c;方便个人模仿或抄袭 方便托管&#xff0c;形成自动化工具链 教育福利&#xff0c;教育参与者暂时免费 讲解完了优势&#xff0c;下面讲注册 Gith…...

决战浏览器渲染:减少重绘(Repaint)与重排(Reflow)的性能优化策略

在现代Web开发中&#xff0c;流畅的用户体验是衡量应用质量的关键指标之一。用户与界面的每一次交互&#xff0c;背后都牵动着浏览器复杂而精密的渲染过程。当这个过程不够高效时&#xff0c;用户就会感受到卡顿、延迟&#xff0c;甚至页面“掉帧”。在众多影响渲染性能的因素中…...

好数对的数目

题目描述 给你一个整数数组 nums。 如果一组数字 (i, j) 满足 nums[i] nums[j] 且 i < j&#xff0c;就可以认为这是一组 好数对。 返回 好数对 的数目。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1,1,3] 输出&#xff1a;4 解释&#xff1a; 有 4 组好…...

C++ STL编程-vector概念、对象创建

vector 概念&#xff1a;是常见的一种容器&#xff0c;被称为“柔性数组”。 在vector中&#xff0c;front()是数组中的第一个元素&#xff0c;back()是数组的最后一个元素。begin()是是指向第一个元素&#xff0c;end()是指向back()的后一个元素 vector的对象创建&#xff0…...

RUI电视桌面中文版:下载安装教程及桌面固件包获取全攻略

在智能电视的使用过程中&#xff0c;一款出色的桌面系统能极大提升用户体验&#xff0c;RUI电视桌面中文版就是这样一个不错的选择。下面为大家详细介绍RUI电视桌面中文版的下载安装教程以及桌面固件包的获取方法。 一、桌面固件包获取 首先是获取桌面固件包。可以通过RUI官方…...

OpenAI 34页最佳构建Agent实践

penAI发布O4&#xff0c;也发布34页最佳构建Agent实践&#xff0c;值得阅读。 什么是Agent&#xff1f; 传统软件使用户能够简化和自动化工作流程&#xff0c;而代理能够以高度独立的方式代表用户执行相同的工作流程。 代理是能够独立地代表您完成任务的系统。 工作流程是必…...

HOOPS Exchange 与HOOPS Communicator集成:打造工业3D可视化新标杆!

一、概述 在工业3D开发、BIM建筑、数字孪生和仿真分析等高端应用场景中&#xff0c;数据格式复杂、模型体量庞大、实时交互体验要求高&#xff0c;一直是困扰开发者的难题。Tech Soft 3D旗下的HOOPS Exchange和HOOPS Communicator&#xff0c;正是解决这类问题的黄金搭档。二者…...

C#进阶学习(六)单向链表和双向链表,循环链表(下)循环链表

目录 &#x1f4ca; 链表三剑客&#xff1a;特性全景对比表 一、循环链表节点类 二、循环链表的整体设计框架 三、循环列表中的重要方法&#xff1a; &#xff08;1&#xff09;头插法&#xff0c;在头结点前面插入新的节点 &#xff08;2&#xff09;尾插法实现插入元素…...

后端程序员工作复盘(一)

1、工作不是为了解决问题&#xff0c;而是为了生活目标。 2、不能当救火队员&#xff0c;要提前预防问题的产生、避免问题的出现。 3、后端表设计和接口设计&#xff0c;要考虑到扩展性&#xff0c;要灵活。无论页面如何变动&#xff0c;后端的改动量都最小&#xff0c;要以不…...

禅道部署进阶指南:从搭建到高可用,全程打怪升级!

禅道在生产环境中的更专业部署方案,包括 Linux 服务器部署、Docker 安装方案、性能优化、安全建议和常见企业级集成方式,适合团队使用或对稳定性、安全性有较高要求的项目。 ✅ 一、企业级部署方案(适合 Linux 环境) 🖥 环境要求 操作系统:CentOS 7+/Ubuntu 18+(推荐)…...

文章记单词 | 第36篇(六级)

一&#xff0c;单词释义 wit [wɪt] n. 智慧&#xff1b;才智&#xff1b;机智&#xff1b;风趣的人dreadful [ˈdredfl] adj. 糟糕透顶的&#xff1b;可怕的&#xff1b;令人畏惧的innocent [ˈɪnəsnt] adj. 无辜的&#xff1b;天真无邪的&#xff1b;无罪的&#xff1b;无…...

Unity使用Newtonsoft.Json本地化存档

我是标题 1.依赖包2.原理&#xff1a;3.代码4.可用优化5.数据加密 1.依赖包 Newtonsoft请在PacakgeManager处下载。 参考&#xff1a;打工人小棋 2.原理&#xff1a; 把要存储的对象数据等使用JsonConvert.SerializeObject(object T)进行序列化为字符串&#xff0c;并且通过…...

Java研学-MybatisPlus(一)

一 概述 MyBatis-Plus&#xff08;简称 MP&#xff09;是一款基于 MyBatis 的增强工具&#xff0c;旨在简化开发、提高效率。它在保留 MyBatis 所有特性的基础上&#xff0c;提供了丰富的功能&#xff0c;减少了大量模板代码的编写。 1 核心特性&#xff1a; ① 无侵入增强&am…...