工程视角:数据结构驱动的应用开发--字典(dictionary),列表(list)与实体

这里写目录标题

  • 业务
    • 业务场景
    • 流程分析
  • 实现
    • 数据访问层(DAL)
    • 业务逻辑层(BLL)
    • 用户界面层(UI)
    • 工具类
  • 设计思路
    • 为什么抽出工具类
    • 关于U层使用字典的好处
    • 工程视角

业务

在这里插入图片描述

业务场景

    在一个金融应用系统中,用户需要登录自己的账户以查看和管理个人信息。系统首先提供一个登录界面,让用户输入必要的登录信息(尽管登录界面未在图片中显示)。一旦用户成功登录,系统将根据用户的登录凭证(如用户名和密码)从数据库中检索该用户的详细账户信息,并将这些信息显示在一个页面上。

流程分析

    从数据库读取数据显示在页面上的流程

  1. 用户登录:
    用户通过登录界面输入账号和密码。
    系统验证用户的登录凭证是否正确。
  2. 检索账户信息:
    一旦登录验证成功,系统会根据用户的账号(卡号、密码等)在数据库中查询对应的账户信息。
    查询的账户信息包括但不限于:卡号、姓名、余额、类型以及注册日期。
  3. 数据处理:
    系统从数据库中检索到的信息需要进行适当的处理,以确保其适用于页面显示(例如,格式化日期、转换货币格式等)。
  4. 页面显示:
    将处理后的数据传递到前端页面。
    页面上将显示用户的卡号、姓名、余额、类型和注册日期等账户信息。
  5. 用户交互:
    用户可以在页面上查看这些信息,并根据需要进行进一步的操作(如修改信息、进行交易等)。

实现

    在这个业务场景中,使用C#结合三层架构(UI层、业务逻辑层BLL、数据访问层DAL)和接口与反射来实现,:

数据访问层(DAL)

    DAL 负责与数据库交互,获取数据。
    使用 SQLHelper 类来执行SQL语句,并返回 DataTable 对象。
    将 DataTable 对象转换为 List,其中dynamic在运行时实际是自定义的实体类,用来存储数据库中的一行数据。

D层的select方法

 public List<dynamic> Select(string cardID){//CustomerEntity customerEntity = (CustomerEntity)enCustomer; //实例化一个消费者实体类//创建sql语句string sql = "select * from T_Customer where cardID=@cardID";//给参数变量进行赋值SqlParameter sqlParameter = new SqlParameter("@cardID",cardID);//建立一个数据表,将查询的结果放到数据表中DataTable dataTable = SQLHelper.GetDataTable(sql, sqlParameter);//创建list集合List<object> list = new List<object>();//并遍历数据表中的数据给list集合foreach (DataRow row in dataTable.Rows) {list.Add(new CustomerEntity(){CardID = Convert.ToInt32(row["cardID"]),//将获取的dataTable表中的数据进行类型转换后赋值给list集合中的数据CardType = row["cardType"].ToString(),Password = row["password"].ToString().Trim(),CardCash = Convert.ToDecimal(row["cardCash"]),Time = Convert.ToDateTime(row["time"]),UserName = row["userName"].ToString(),});}return list;}

业务逻辑层(BLL)

    BLL 接收来自UI层的请求,调用DAL层获取数据,并进行业务逻辑处理。
    BLL层可以将 List转换为 Dictionary<Key, Value>,其中 Key 通常是唯一标识符(如账号),Value 是整个实体或实体的部分属性集合。

public Dictionary<string, string> GetDictionary(params string[] values)
{ISelect iCustomerSelect = AbstractFactory.Factory.CreateConcreteClass("ConcreteDAL", "DAL", "T_Customer");List<dynamic> list = iCustomerSelect.Select(values[0]);Dictionary<string, string> dictionary = new Dictionary<string, string>();foreach (CustomerEntity row in list)   //遍历传入的数据添加至字典{dictionary.Add("txtCard", row.CardID.ToString());dictionary.Add("txtCardType", row.CardType.ToString());dictionary.Add("txtCash", row.CardCash.ToString());dictionary.Add("txtTime", row.Time.ToString());dictionary.Add("txtUserName", row.UserName.ToString());}return dictionary;  //将字典返回
}

    但请注意,通常BLL层会直接返回List或更复杂的对象,如ViewModel,而不是直接返回Dictionary。Dictionary的使用更多是在内部处理中,以便快速查找或映射数据。(这里为了说明Dictionary的好处)

用户界面层(UI)

UI 层负责展示数据和接收用户输入。
UI层通过接口和反射调用BLL层的方法,获取数据并展示。
UI层接收到的数据可以是这里设计为 Dictionary<TKey, TValue>

private void tabCardContent_Enter(object sender, EventArgs e)
{Dictionary<string, string> dictionary = new Dictionary<string, string>(); //实例化一个字典InvariableEntity invariable = new InvariableEntity();   //实例化常量类IDictionary iDictionary = AbstractFactory.Factory.CreateConcreteClass("ConcreteBLL", "BLL", "T_Customer");dictionary = iDictionary.GetDictionary(invariable.UserID); //接受外观层传入的数据try{TextAssignment textAssingment = new TextAssignment(); //实例化Utility的文本赋值方法textAssingment.AddData(tabContent, dictionary); //将选项卡名称和已经赋值的字典传入方法中进行添加}catch (Exception ex){MessageBox.Show(ex.Message);  //将未查到的信息通知给用户}
}

工具类

向文本框赋值的方法,抽出来一个工具类

public class TextAssignment
{/// <summary>/// 文本赋值/// </summary>/// <param name="control">要赋值的tab选项卡名称</param>/// <param name="dictionary">字典名称</param>public void AddData(Control controlTab, Dictionary<string, string> dictionary){string row;//定义一个字符串接受返回值foreach (Control control in controlTab.Controls)   //遍历control控件,{if (control is TextBox)  //如果空间中包含文本框{dictionary.TryGetValue(control.Name, out row);  //根据控件名称传出对应的value值control.Text = row;  //将值赋值给对应的文本框}}}
}

设计思路

为什么抽出工具类

    抽出TextAssignment这样的工具类来向文本框赋值,而不是直接在代码中使用实体或数据直接赋值给文本框,有几个重要的原因和好处:

1、解耦和复用:
    解耦:通过将赋值逻辑封装在独立的类中,业务逻辑代码(如UI层代码)与具体的赋值操作解耦。意味着如果将来需要改变赋值逻辑(比如添加验证、修改数据格式等),只需修改这个工具类,而不需要去修改业务逻辑代码。
    复用:这个工具类可以在多个地方被复用。如果有多个地方需要类似的赋值操作,可以直接调用这个工具类的方法,而不是每次都写一遍相同的逻辑。

2、清晰性和可维护性:
    清晰性:通过将赋值逻辑放在专门的类中,代码更加清晰易懂。其他开发者(或未来的你)在查看代码时,可以更容易地理解各个部分的功能和职责。
    可维护性:当需要修改或扩展赋值逻辑时,只需要关注这个工具类,而不需要在整个项目中搜索所有相关的赋值代码。

3、灵活性和可扩展性:
    灵活性:你可以轻松地修改这个工具类来适应不同的需求。比如,你可以添加额外的参数来控制赋值行为(如是否进行验证、是否允许空值等)。
    可扩展性:如果需要支持除了文本框以外的其他控件的赋值(如下拉列表、复选框等),可以在工具类中添加更多的逻辑来处理这些控件,而不需要在每个使用点都进行改动。

4、测试:
    将赋值逻辑封装在单独的类中,可以更容易地对其进行单元测试。可以创建不同的测试场景来验证赋值逻辑的正确性,而不需要运行整个应用程序。

5、遵循设计模式:
    抽出工具类也符合一些设计模式的原则,如单一职责原则(一个类应该只负责一项职责),开放封闭原则(软件实体(类、模块、函数等)应该对扩展开放,对修改关闭)等。

    除了上面经常说的软件工程的思想,还有一点,也是我特别想说的–变量的思想

    给文本框赋值,使用实体的属性不是很方便吗,为什么要引入字典,来看一下,这个逻辑,给文本框赋值,需要实体.属性,假设使用泛型可以接收任何实体,那么实体就变成了一个变量,用A来表示,为了让整体(实体.属性)变得有通用性,就要整体都是变量,假设属性是b,为了整体是变量,就必须让实体是变量,属性也是变量–A.b.但是每个实体的属性是特定的,怎么让它是变量,只有字典这种结构更适合。

如果没理解,再从业务说起:

    在创建一个能够通用地处理不同实体对象并将其属性映射到UI控件(如文本框)的场景中,存在几个挑战,主要是因为不同的实体类会有不同的属性集。看这里的几个解决方案

使用反射:
    反射允许在运行时检查对象的类型并访问其属性。但是,它可能会引入性能开销,并且如果属性名或类型不匹配,可能会导致运行时错误。

定义接口或基类:
    创建一个包含所有可能属性的接口或基类,并让实体类实现该接口或继承自该基类。然而,这要求所有实体都有相同的属性集,这在大多数情况下是不切实际的。

使用字典:
    字典提供了一种灵活的方式来映射键(通常是字符串)到值(可以是任何类型)。在这个场景下,可以将实体对象的属性名作为键,将属性值作为值存储在字典中。这样,无论实体对象的类型如何,都可以使用相同的逻辑来处理这些字典项,并将它们映射到UI控件上。

为什么使用字典可能是最佳选择
    灵活性:字典可以包含任意数量的键值对,且键和值可以是任意类型(尽管在实际应用中,键通常是字符串,值是与UI控件相关的数据类型)。这使得字典能够轻松适应不同实体对象的属性集。

    简单性:与反射或表达式树相比,字典的API相对简单且易于使用。不需要编写复杂的代码来动态解析属性名或构建查询。

    性能:虽然反射可能会引入性能开销,但字典的查找和更新操作通常很快。此外,如果只需要在UI加载时从实体对象填充到字典中,并在之后直接使用这些字典项来更新UI,那么性能影响可能很小。

    总之,虽然直接使用实体或数据给文本框赋值在某些情况下是可行的,但在更复杂或更大型的项目中,使用工具类来封装这类操作通常会带来更好的代码质量和可维护性。

关于U层使用字典的好处

    在UI层使用 Dictionary 而不是 List 或实体类,有以下几个潜在的好处(尽管这些好处可能并不总是适用):

    快速查找:如果你需要频繁地根据某个键(如账号)来查找数据,Dictionary 提供了非常快的查找速度(接近O(1))。

    减少内存占用(在某些情况下):如果你只需要存储数据的某个子集,或者只需要快速访问数据的一部分,使用 Dictionary 可能比存储整个实体对象更节省内存。

    简化数据访问:在某些情况下,使用 Dictionary 可以使数据访问逻辑更加清晰和简单。
然而,Dictionary 也有其局限性,比如它不保证元素的顺序(在.NET Core 3.5及以后的版本中,Dictionary 的枚举顺序是确定的,但它仍然不是有序的集合),并且它只能根据一个键来索引数据。

    字典的出现 是为了提供一种更高效、更灵活的方式来存储和访问键值对数据。在编程中,我们经常需要快速查找或映射数据,而 Dictionary 正好满足了这一需求。

    最后,选择使用 List、Dictionary 还是其他数据结构,应该基于具体需求和场景来决定。在UI层,通常更倾向于使用易于绑定和展示的数据结构,如 List 或自定义的ViewModel类。

工程视角

    在计算机科学和软件工程领域,数据结构是组织、存储和管理数据的方式,它们对于设计高效、可扩展和可维护的软件系统至关重要。字典、List(列表)与实体都是常见且重要的数据结构,它们在数据处理、算法设计和系统开发中扮演着核心角色。

  1. 字典(Dictionary)

定义:
字典是一种通过键(Key)来访问其对应值(Value)的数据结构。每个键都是唯一的,并且与一个值相关联。这种键值对的关系使得字典成为了一种非常灵活和高效的数据存储方式。

具体实现:

    在许多编程语言中,字典都是通过哈希表(Hash Table)实现的。哈希表利用哈希函数将键映射到数组中的一个索引位置,从而实现对字典的快速访问。
Python中的dict类型就是一个典型的字典实现,它支持通过键来快速检索、插入和删除元素。
特点:

    快速访问:通过键可以快速定位到对应的值,时间复杂度通常为O(1)(在平均情况下)。
    无序性:字典中的元素是无序的,即它们没有固定的顺序。
    键值唯一性:字典中的键必须是唯一的,但值可以重复。

  1. List(列表)

定义:
列表是一种有序的数据结构,它可以包含多个元素,并且这些元素可以是不同类型的。列表中的元素可以通过索引来访问,索引通常是从0开始的。

具体实现:

    列表在内存中是连续存储的,这使得通过索引访问元素变得非常高效。
Python中的list类型就是一个典型的列表实现,它支持动态扩容,即在运行时可以添加或删除元素。

特点:

    有序性:列表中的元素是有序的,即它们有固定的顺序。
随机访问:通过索引可以立即访问任何位置的元素,时间复杂度为O(1)。
    动态性:列表的大小可以在运行时动态改变,支持在任意位置插入或删除元素(尽管这可能会导致后续元素的移动,从而影响效率)。

  1. 实体(Entity)

定义:
    在软件工程中,实体通常指的是具有特定属性和行为的对象或数据结构的实例。实体可以是简单的数据结构(如字典或列表),也可以是复杂的数据结构(如类实例)。

关系:

    实体可以包含字典或列表作为其属性,用于存储和管理相关数据。
    例如,一个用户实体可能包含一个字典来存储用户的个人信息(如姓名、年龄等),以及一个列表来存储用户的订单信息。

特点:

    封装性:实体通常封装了数据和操作这些数据的方法,提供了对数据的保护和抽象。
可重用性:实体可以被多次实例化,并在不同的上下文中重复使用。
    多态性:在面向对象编程中,实体(类实例)可以支持多态性,即不同的实体对象可以响应相同的消息(方法调用)但以不同的方式执行。

    综上所述,字典、List(列表)与实体都是重要的数据结构,它们在数据结构驱动的应用开发中扮演着关键角色。字典提供了快速访问和键值对存储的能力;列表提供了有序和动态数据集合的能力;而实体则通过封装、可重用性和多态性为软件系统提供了丰富的数据模型和行为支持。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaScript】虚拟 DOM

虚拟 DOM 是⼀层对真实DOM的抽象&#xff0c;以JavaScript 对象 (VNode 节点) 作为基础的树&#xff0c;⽤对象的属性来描述节点&#xff0c;最终可以通过⼀系列操作使这棵树映射到真实环境上。 虚拟DOM 表现为⼀个 Object对象。并且最少包含标签名 (tag)、属性 (attrs) 和⼦元…

多路复用IO、TCP并发模型

时分复用 CPU单核在同一时刻只能做一件事情&#xff0c;一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片&#xff0c;不同事件流的时间片交替进行)。在计算机系统中&#xff0c;我们用线程或者进程来表示一条执行流&#xff0c;通过不同的线程或进程在操作系…

HarmonyOS 本地真机运行

目录 官网地址 1.开发工具设置签名 2.手机开启开发者模式 3.使用USB连接方式 4.使用无线调试连接方式 5.常见的问题 官网地址 使用真机运行应用 使用本地真机运行应用/服务 1.开发工具设置签名 官网应用/服务签名 1.左上角文件--项目结构-勾选自动生成签名-Sign in登录 2…

WEB前端08-综合案例(动态表格)

使用 HTML、CSS 和 JavaScript 创建动态表格 在本教程中&#xff0c;我们将创建一个动态表格&#xff0c;允许用户添加行、选择项目&#xff0c;并执行批量操作&#xff0c;如全选或删除选中的行。我们将通过 HTML、CSS 和 JavaScript 来实现这一功能。让我们逐步了解每个部分…

Vue前端工程化 安装Vue-Cli与node.js 最详细步骤(带图展示)

一、安装NodeJS 1.官网下载 https://nodejs.org/zh-cn 2.直接从百度网盘中提取安装 链接&#xff1a;https://pan.baidu.com/s/1OKhHZUwPCLamvd_08Vxx0g 提取码&#xff1a;61rw 3.开始安装 二、验证NodeJS环境变量 1.Win R 输入cmd打开控制面板 2.输入 node -v 如果出…

NVIDIA 全面转向开源 GPU 内核模块

NVIDIA 全面转向开源 GPU 内核模块 文章目录 NVIDIA 全面转向开源 GPU 内核模块支持的 GPU安装程序更改使用带有 CUDA 元包的包管理器 使用运行文件使用安装帮助脚本包管理器详细信息dnf&#xff1a;Red Hat Enterprise Linux、Fedora、Kylin、Amazon Linux 或 Rocky Linuxzypp…

程序员信息差,这个工具你必须知道

身为程序员&#xff0c;你是否也曾遇到过这样的情况&#xff1a;费尽心思搭建好服务器&#xff0c;开发好接口API&#xff0c;结果上线后却发现用户体验并不好&#xff0c;甚至还因为各种BUG忙得焦头烂额&#xff1f;别担心&#xff0c;你不是一个人。事实上&#xff0c;很多开…

用神经网络求解微分方程

微分方程是物理科学的主角之一&#xff0c;在工程、生物、经济甚至社会科学中都有广泛的应用。粗略地说&#xff0c;它们告诉我们一个量如何随时间变化&#xff08;或其他参数&#xff0c;但通常我们对时间变化感兴趣&#xff09;。我们可以了解人口、股票价格&#xff0c;甚至…

Python 使用TCP\UDP协议创建一个聊天室

server端代码&#xff1a; #encodingutf-8 # 服务端代码 import socketdef server():server_socket socket.socket(socket.AF_INET, socket.SOCK_STREAM)host socket.gethostname()port 12345server_socket.bind((host, port))server_socket.listen(5)print(等待客户端连接…

使用Gradle构建编译Spring boot 2.7.x

一、环境准备 JDK 1.8Spring boot 2.7.xGradle 7.5.1 (安装参考&#xff1a;win11安装Gradle)Idea 2023.1 二、源码导入gitee(可选) 按需导入。如果能科学上网&#xff0c;可跳过这一步。 为避免github访问不稳定问题&#xff0c;建议将对应的代码导入到gitee。然后通过git管…

内存泄漏详解

文章目录 什么是内存泄漏内存泄漏的原因排查及解决内存泄漏避免内存泄漏及时释放资源设置合理的变量作用域及时清理不需要的对象避免无限增长避免内部类持有外部类引用使用弱引用 什么是内存泄漏 内存泄漏是指不使用的对象持续占有内存使得内存得不到释放&#xff0c;从而造成…

【Java语法基础】1、变量、运算符、输入输出

1.变量、运算符、输入输出 跟C一样&#xff0c;先把必须写的框架写出来&#xff1a; package org.example; public class Main{public static void main(String[] args){//在里面写实际的代码} }变量 必须先定义&#xff0c;才能使用。与C、C差不多。 没有赋初值的变量无法…

windows网络应急排查

一、系统排查 msinfo32 #GUI显示的系统信息systeminfo #简单了解系统信息用户信息排查 排查恶意账号&#xff1a; 黑客喜欢建立相关账号用作远控: 1.建立新账号2.激活默认账号3.建立隐藏账号(windows中账号名$)cmd方法 net user #打印用户账号信息 ---看不到$结尾的隐藏账…

Linux - 进程的概念、状态、僵尸进程、孤儿进程及进程优先级

目录 进程基本概念 描述进程-PCB task_struct-PCB的一种 task_struct内容分类 查看进程 通过系统目录查看 通过ps命令查看 通过系统调用获取进程的PID和PPID 通过系统调用创建进程- fork初始 fork函数创建子进程 使用if进行分流 Linux进程状态 运行状态-R 浅度睡眠状态-S…

Apache Filnk----入门

文章目录 Flink 概述Flink 是什么有界流和无界流有状态流处理Flink 特点Flink vs SparkStreamingFlink 分层API Flink 快速上手WordCount 代码编写批处理流处理读取socket文本流 Flink 概述 Flink 是什么 有界流和无界流 无界数据流: 有定义流的开始&#xff0c;但没有定义流…

ts一些解决vscode飘红的方法

1、查看是否有些ts的数据类型定义问题&#xff0c;属性缺少或者属性类型不对 把对应属性加上即可 2、在飘红的代码前面设置// ts-ignore忽略此行校验&#xff08;不过一般不建议用这个方法&#xff09; 3、移除高版本不用的属性&#xff08;版本属性兼容问题&#xff09; 原因…

PP-Human行为识别(RTSP协议视频流实时检测)

基于PaddleDetection本地实现PP-Human行为识别模块&#xff08;RTSP协议视频流实时检测&#xff09; 项目介绍环境准备1. Anaconda 创建环境2. 获取 PaddleDetection3. 获取 [MediaMTX](https://github.com/bluenviron/mediamtx/releases/tag/v1.8.4)4. FFmpeg 获取5. VLC 获取…

.NET开源、简单、实用的数据库文档生成工具

前言 今天大姚给大家分享一款.NET开源&#xff08;MIT License&#xff09;、免费、简单、实用的数据库文档&#xff08;字典&#xff09;生成工具&#xff0c;该工具支持CHM、Word、Excel、PDF、Html、XML、Markdown等多文档格式的导出&#xff1a;DBCHM。 支持的数据库 Sq…

IEEE官方列表会议 | 第三届能源与环境工程国际会议(CFEEE 2024)

会议简介 Brief Introduction 2024年第三届能源与环境工程国际会议(CFEEE 2024) 会议时间&#xff1a;2024年12月2日-4日 召开地点&#xff1a;澳大利亚凯恩斯 大会官网&#xff1a;CFEEE 2024-2024 International Conference on Frontiers of Energy and Environment Engineer…

Android APP 音视频(01)MediaCodec解码H264码流

说明&#xff1a; 此MediaCodec解码H264实操主要针对Android12.0系统。通过读取sd卡上的H264码流Me获取视频数据&#xff0c;将数据通过mediacodec解码输出到surfaceview上。 1 H264码流和MediaCodec解码简介 1.1 H264码流简介 H.264&#xff0c;也被称为MPEG-4 AVC&#xff…