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

C#设计模式——抽象工厂模式(重点)


文章目录

  • 项目地址
  • 一、抽象工厂模式
    • 1.1 特性
    • 1.2 使用反射获取特性标记的类
    • 1.3 完整代码


项目地址

  • 教程作者:
  • 教程地址:
  • 代码仓库地址:
  • 所用到的框架和插件:
dbt 
airflow

一、抽象工厂模式

  1. 工厂方法模式依然存在一个问题就是,一堆的 switch用来根据符号判断;if或者switch都是描述了一段关系,运算符和具体工厂对象的对应关系,如何直接根据符号就可以自动获取对应的类,并且自动创建实例呢?

1.1 特性

  • 什么是特性?
    通过Attribute特性,根据输入的符号,直接将符号+和cal = new Add();对应起来,特性类似于一个装饰器,装饰器装饰的类,就拥有了这个对应关系;
    往往和反射一起结合使用
  1. 创建一个特性,用来描述运算符和具体类的关系
//①使用特性Attribute来标记类的作用
public class OperToFactoryAttribute : Attribute
{public string Oper { get; } public OperToFactoryAttribute(string oper){this.Oper = oper;}
}
  1. 使用创建好的特性去标记运算类
//②使用特性Attribute来标记类的作用
//2.通过子类实现加法的创建
[OperToFactoryAttribute("+")]
public class AddFactory : ICalFactory
{public ICal GetCalculator(){return new Add();}
}

至此,运算符和对应需要的类已经创建完成,程序运行后,当用户输入了符号,我们应该通过这个对应关系,就可以找到这个类,然后进行实例化,计算

1.2 使用反射获取特性标记的类

  1. 根据用户的操作符,返回一个对象,
  2. 通过字典来存储对应关系
  3. 通过反射获取所有的程序集
  4. 获取所有的类型
  5. 通过判断获取AddFactory,SubFactory,MulFactory,DivFactory,找到他们的共性,都是继承了ICalFactory接口,并且排除ICalFactory自己

1.3 完整代码


using System.ComponentModel;
using System.Reflection;public class program
{static void Main(){Console.WriteLine("输入number1:");double d1 = Convert.ToDouble(Console.ReadLine());Console.WriteLine("输入number2:");double d2 = Convert.ToDouble(Console.ReadLine());Console.WriteLine("输入运算符:");string op = Console.ReadLine();//13.执行反射里的构造函数,创建符号和类的对应关系的字典ReflectionFactory rf = new ReflectionFactory();//15.通过运算符来创建工厂ICalFactory calFactory = rf.CreateFactory(op);//16.通过具体的运算类来计算结果ICal calculator = calFactory.GetCalculator();double res = calculator.getResult(d1, d2);Console.WriteLine(res);}
}//1.创建特性Attribute来标记类的作用
public class OperToFactoryAttribute : Attribute
{public string Oper { get; } public OperToFactoryAttribute(string oper){this.Oper = oper;}
}//声明一个接口,先将创建对象的这个过程封装成抽象
public interface ICalFactory
{ICal GetCalculator();
}//3.通过反射,程序运行后,获取特性标记的类,然后通过反射创建对象
public class ReflectionFactory
{//4.创建字典,存储符号和类的对应关系Dictionary<string, ICalFactory> dic = new Dictionary<string, ICalFactory>();//5.构造函数public ReflectionFactory(){//6.通过反射获取所有的程序集Assembly asm = Assembly.GetExecutingAssembly();//7.获取所有的类型Type[] types = asm.GetTypes();foreach (var type in types){//8.通过判断获取AddFactory,SubFactory,MulFactory,DivFactoryif (typeof(ICalFactory).IsAssignableFrom(type) && !type.IsInterface){//9.获取特性OperToFactoryAttribute otfa = type.GetCustomAttribute<OperToFactoryAttribute>();//10.判断是否为空if (otfa != null){//11.将特性和类的对应关系存储到字典中,根据type创建对象dic.Add(otfa.Oper, Activator.CreateInstance(type) as ICalFactory);}}}}//12.通过运算符来创建工厂public ICalFactory CreateFactory(string oper){//13. 从字典里查找对应关系if (dic.ContainsKey(oper)){return dic[oper];}return null;}
}//2.使用特性Attribute来标记类的作用
[OperToFactoryAttribute("+")]
public class AddFactory : ICalFactory
{public ICal GetCalculator(){return new Add();}
}[OperToFactoryAttribute("-")]
public class SubFactory : ICalFactory
{public ICal GetCalculator(){return new Sub();}
}[OperToFactoryAttribute("*")]
public class MulFactory : ICalFactory
{public ICal GetCalculator(){return new Mul();}
}[OperToFactoryAttribute("/")]
public class DivFactory : ICalFactory
{public ICal GetCalculator(){return new Div();}
}//计算类的接口
public interface ICal
{double getResult(double num1, double num2);
}public class Add : ICal
{public double getResult(double num1, double num2){return num1 + num2;}
}
public class Sub : ICal
{public double getResult(double num1, double num2){return num1 - num2;}
}public class Mul : ICal
{public double getResult(double num1, double num2){return num1 * num2;}
}public class Div : ICal
{public double getResult(double num1, double num2){return num1 / num2;}
}

相关文章:

C#设计模式——抽象工厂模式(重点)

文章目录 项目地址一、抽象工厂模式1.1 特性1.2 使用反射获取特性标记的类1.3 完整代码 项目地址 教程作者&#xff1a;教程地址&#xff1a; 代码仓库地址&#xff1a; 所用到的框架和插件&#xff1a; dbt airflow一、抽象工厂模式 工厂方法模式依然存在一个问题就是&…...

全新AI模型家族登场:完全可复现的开源语言模型OLMo 2

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

用Matlab和SIMULINK实现DPCM仿真和双边带调幅系统仿真

1、使用SIMULINK或Matlab实现DPCM仿真 1.1 DPCM原理 差分脉冲编码调制&#xff0c;简称DPCM&#xff0c;主要用于将模拟信号转换为数字信号&#xff0c;同时减少数据的冗余度以实现数据压缩。在DPCM中&#xff0c;信号的每个抽样值不是独立编码的&#xff0c;而是通过预测前一…...

RabbitMQ的交换机总结

1.direct交换机 2.fanout交换机...

Android so库的编译

在没弄明白so库编译的关系前,直接看网上博主的博文,常常会觉得云里雾里的,为什么一会儿通过Android工程cmake编译,一会儿又通过NDK命令去编译。两者编译的so库有什么区别? android版第三方库编译总体思路: 对于新手小白来说搞明白上面的总体思路图很有必…...

2024年底-Arch linux或转为0BSD许可证!

原文&#xff1a;https://archlinux.org/news/providing-a-license-for-package-sources/ 解读&#xff1a;Arch Linux社区通过RFC 40达成共识&#xff0c;决定将所有软件包源代码更改为0BSD许可证。 0BSD许可证是什么&#xff1f;&#xff1a;这是一个非常自由的开源许可证&a…...

深入解析音视频流媒体SIP协议交互过程

一、引言 在音视频流媒体传输过程中&#xff0c;SIP&#xff08;Session Initiation Protocol&#xff09;协议发挥着举足轻重的作用。本文将详细全面地介绍音视频流媒体传输中的SIP协议&#xff0c;包括其基本概念、交互过程、关键信令以及应用场景 二、SIP协议基本概念 1.…...

linux安装mysql8.0.40

一、下载MySQL安装包 1.查看glibc版本 rpm -qa | grep glibc 2.到mysql官网下载安装包 ​ 二、解压安装 1.上传压缩包纸/usr/local 目录下&#xff0c;解压&#xff1a; tar -xvf mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz 2.重命名&#xff1a; mv mysql-8.0.40-linux-…...

Java基础之控制语句:开启编程逻辑之门

一、Java控制语句概述 Java 中的控制语句主要分为选择结构、循环结构和跳转语句三大类&#xff0c;它们在程序中起着至关重要的作用&#xff0c;能够决定程序的执行流程。 选择结构用于根据不同的条件执行不同的代码路径&#xff0c;主要包括 if 语句和 switch 语句。if 语句有…...

如何还原 HTTP 请求日志中的 URL 编码参数?详解 %40 到 @

在记录HTTP请求的日志中出现了这样的情况&#xff1a; 2024-11-20 11:12:49 INFO network_request gz_login 96 Body: countryAbbrCN&countryCode86&email1222405567%40qq.com&password12354e50456db124f9f34e2789308733&type1 出现这种情况的原因是&#x…...

usb_cam ros包话题说明,image transport包使用

1. /usb_cam/image_raw 类型: sensor_msgs/Image 内容: 摄像头采集的原始图像数据。 用途: 图像处理和分析&#xff0c;例如使用 OpenCV 处理图像。视频流可达10MB/s 图像流查看&#xff0c;例如用 rqt_image_view 进行显示&#xff1a; 2./usb_cam/image_raw/compressed …...

微前端-MicroApp

微前端即是由一个主应用来集成多个微应用&#xff08;可以不区分技术栈进行集成&#xff09; 下面是使用微前端框架之一 MicroApp 对 react微应用 的详细流程 第一步 创建主应用my-mj-app 利用脚手架 npx create-react-app my-mj-app 快速创建 安装 npm install --save rea…...

Unity UGUI 垂直循环复用滚动

一 基础类 在unity里面新建这几个类 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; /// <summary> /// 垂直方向滚动 /// </summary> public class CustomScroll:MonoBehaviour {public …...

Spring MVC 深度剖析:优势与劣势全面解读

文章目录 Spring MVC 优势1. **松耦合**2. **易于测试**3. **灵活性**4. **强大的配置机制**5. **异常处理**6. **国际化支持**7. **数据验证**8. **安全性**9. **性能优化** Spring MVC 劣势1. **学习曲线**2. **配置复杂性**3. **性能开销**4. **视图技术限制**5. **社区和支…...

力扣hot100-->前缀和/前缀书/LRU缓存

前缀和 1. 560. 和为 K 的子数组 中等 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#…...

Three.js CSS2D/CSS3D渲染器

在Three.js开发过程中&#xff0c;有时需要将 HTML 元素与 Three.js 渲染的 3D 场景相结合&#xff0c;这就需要用到 CSS2DRenderer 和 CSS3DRenderer。本文将详细介绍这两种渲染器的原理及其应用 一、CSS2DRenderer 渲染器 概述 CSS2DRenderer 渲染器用于在 3D 场景中渲染纯…...

mongodb文档字符串批量替换

【mongodb文档字符串批量替换脚本语句】 前言&#xff1a; 1、本方式对于数据量大的情况不适用&#xff0c;执行可能比较慢&#xff1b; 2、数据量大的情况&#xff0c;个人推荐代码层面解决&#xff0c;多线程替换更快&#xff1a; &#xff08;1&#xff09;写实体类的方式…...

前端安全和解决方案

提到这个我可能想到的就是不要暴露太多的账号密码信息。一些页面的请求和操作要加上权限。 然后下面就详细的介绍前端可能遇到的安全问题以及解决方法。 首先比较常见的前端的安全性问题就是跨站脚本攻击&#xff08;XSS&#xff09;。跨站请求伪造&#xff08;csrf&#xff…...

Tlias智能辅助学习系统-部门管理

包括查询、新增、删除、修改功能 控制层 package com.itheima.controller;import com.itheima.pojo.Dept; import com.itheima.pojo.Result; import com.itheima.service.DeptService; import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.XSlf4j; import org.spr…...

React第十节组件之间传值之context

1、Context 使用creatContext() 和 useContext() Hook 实现多层级传值 概述&#xff1a; 在我们想要每个层级都需要某一属性&#xff0c;或者祖孙之间需要传值时&#xff0c;我们可以使用 props 一层一层的向下传递&#xff0c;或者我们使用更便捷的方案&#xff0c;用 creatC…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

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;规则组 注入…...

boost::filesystem::path文件路径使用详解和示例

boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类&#xff0c;封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解&#xff0c;包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...