工程视角:数据结构驱动的应用开发--字典(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.rhkb.cn/news/382666.html

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

相关文章

【益智问题】十三球称重

十三球称重 问题描述解决方案 问题描述 有13个外表一模一样的小球产品&#xff0c;其中有一个是次品&#xff0c;其质量与其他12个略有差别&#xff0c;但不知道是重还是轻。这13个球上都有标号&#xff0c;现在给你-架天平&#xff0c;只能使用三次&#xff0c;把这个次品小球…

Elasticsearch:Golang ECS 日志记录 - zap

ECS 记录器是你最喜欢的日志库的格式化程序/编码器插件。它们可让你轻松地将日志格式化为与 ECS 兼容的 JSON。 编码器以 JSON 格式记录日志&#xff0c;并在可能的情况下依赖默认的 zapcore/json_encoder。它还处理 ECS 错误格式的错误字段记录。 默认情况下&#xff0c;会添…

58、主从复制数据库+读写分离

mysql的主从复制和读写分离&#xff08;面试问原理&#xff09; mysql的主从复制和读写分离&#xff1a; 主从复制 面试必问 主从复制的原理。 读写分离&#xff0c;MHA 一、主从复制 1.1、主从复制的模式&#xff1a; 1、mysql的默认模式&#xff1a; 异步模式&#xf…

Three.js 官方文档学习笔记

Address&#xff1a;Three.js中文网 (webgl3d.cn) Author&#xff1a;方越 50041588 Date&#xff1a;2024-07-19 第一个3D案例—创建3D场景 创建3D场景对象Scene&#xff1a; const scene new THREE.Scene(); 创建一个长方体几何对象Geometry&#xff1a; const geomet…

FTP、NFS、SAMBA系统服务

⼀、rsync托管xinetd 1 、为什么要进⾏服务托管 独⽴服务&#xff1a;独⽴启动脚本 ssh ftp nfs dns ... 依赖服务 : 没有独⽴的启动脚本 rsync telnet 依赖 xinetd 服务&#xff08;独⽴服务&#xff09; 2 、如何将 rsync 托管给 xinetd 服务去管理&#xff1f; 第⼀步&am…

VMware中Ubuntu磁盘空间的清理

最近发现Ubuntu占用空间过大&#xff0c;在网上找了一些方法&#xff0c;在这里总结一下。 1.删除快照 把不需要的快照删除&#xff0c;但要注意删除快照可能会影响到后续的快照链。每个快照依赖于前面的快照。如果删除一个中间快照&#xff0c;虚拟机可能无法找到完整的差异…

leetcode 513.找树左下角的值

1.题目要求: 代码块: 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。2.此题思路: 1.创建队列&#xff0c;出队函数和入队函数: //创建队列 typedef struct queuet{struct TreeNode* value;struct queue* n…

IB user verbs介绍

本文来自对内核源代码文档/Documentation/infiniband/user_verbs.rst的翻译和理解。 在Infiniband设备帮助下&#xff0c;跨计算机的两个进程可以相互访问对方的虚地址空间。在Linux操作系统上&#xff0c;支持进程能直接访问本地Infiniband设备的资源&#xff0c;从而实现跨机…

TeamViewer手机端APP提示:请先验证账户

当你在手机端下载安装了TeamViewerAPP后&#xff0c;需要你先登录个人账号&#xff0c;然后还会要求你验证账户&#xff0c;同时跳转到一个网址中&#xff0c;但是这个网址并没有自动跳转到验证账户的位置。 解决办法&#xff1a; 在手机浏览器中进入下面这个网址&#xff1a;…

鸿蒙语言基础类库:【@system.vibrator (振动)】

振动 说明&#xff1a; 本模块首批接口从API version 4开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。从API Version 8开始&#xff0c;该接口不再维护&#xff0c;推荐使用新接口[ohos.vibrator]。该功能使用需要对应硬件支持&#xff0c;仅支持…

VMware虚拟机无法访问互联网

一、什么情况下需要访问互联网 在某些情况下&#xff0c;VMware虚拟机需要通过访问互联网去获取外部资源&#xff0c;例如进行yum安装或者wget拉取操作等等。 二、处理方法 2.1.检查虚拟机网络模式和服务状态 虚拟机的网络模式需要使用 NAT 模式。 VMware NAT Service服务…

Delphi 11.2 配置Android SDK 环境

打开 Delphi 11 点击 Tools–Options… 然后点击 Deployment–SDK Manager–Add… 这里如果配置64位就选 Android 64-bit&#xff0c;如果配置32位就选 Android 32-bit 点击 Select an SDK version–Add New… 有警告图标的就是有问题的项&#xff0c;需要手动更新一下&#xf…

微信小程序开发:项目程序代码构成

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

PostgreSQL创建表和自增序列

一、创建表&#xff1a; 注意&#xff1a; 1、在mysql没有序列的概念&#xff0c;id自增通过auto_increment实现&#xff1b; 2、pgsql没有auto_increment的概念&#xff0c;如何实现id自增&#xff1f;有两种方式&#xff1a; 方式一&#xff1a;创建序列&#xff0c;绑定…

Android lmkd机制详解

目录 一、lmkd介绍 二、lmkd实现原理 2.1 工作原理图 2.2 初始化 2.3 oom_adj获取 2.4 监听psi事件及处理 2.5 进程选取与查杀 2.5.1 进程选取 2.5.2 进程查杀 三、关键系统属性 四、核心数据结构 五、代码时序 一、lmkd介绍 Android lmkd采用epoll方式监听linux内…

SpringBoot连接PostgreSQL+MybatisPlus入门案例

项目结构 一、Java代码 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://mave…

客户案例 | 识货基于向量检索服务 Milvus 版搭建电商领域的向量数据检索平台

阿里云的Milvus服务以其性能稳定和功能多样化的向量检索能力&#xff0c;为识货团队在电商领域的向量检索场景中搭建业务系统提供了强有力的支持。该服务的分布式扩展能力不仅可靠&#xff0c;而且能够适应日益增长的数据规模。 一、客户介绍 识货&#xff0c;成立于2012年6月…

Selenium之execute_script()方法执行js脚本

目录 场景应用和使用 页面滚动 获取返回值 返回JavaScript定位的元素对象 修改元素属性 弹出提示框 场景应用和使用 在自动化测试中&#xff0c;部分场景无法使用自动化Selenium原生方法来进行测试&#xff1a; 滚动到某个元素&#xff08;位置&#xff09; 修改…

水利行业的智慧转型之路:分析智慧水利的核心要素与优势,展望其在提升水资源利用效率、保障水安全方面的广阔前景

目录 引言 一、智慧水利的核心要素 1. 物联网技术 2. 大数据与云计算 3. 人工智能与机器学习 4. 移动互联网与GIS技术 5. 标准化与信息安全 二、智慧水利的优势 1. 提高水资源利用效率 2. 增强水灾害防御能力 3. 提升水环境治理水平 4. 促进水利服务智能化 三、展望…

响应式商标知识产权企业网站源码系统 带模版以及搭建部署教程

系统概述 响应式商标知识产权企业网站源码系统是一款专门为商标知识产权企业打造的综合性网站平台。它融合了先进的技术和设计理念&#xff0c;旨在为企业提供一个全面展示自身形象、业务能力和专业服务的数字化窗口。 该系统采用了现代化的架构和开发方式&#xff0c;具备高度…