工程视角:数据结构驱动的应用开发--字典(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.mzph.cn/diannao/49293.shtml

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

相关文章

.netcore TSC打印机打印

此文章给出两种打印案例&#xff0c; 第一种是单列打印&#xff0c;第二种是双列打印 需要注意打印机名称的设置&#xff0c;程序中使用的打印机名称为999&#xff0c;电脑中安装打印机时名称也要为999。 以下是我在使用过程中总结的一些问题&#xff1a; 一 TSC打印机使用使…

【Node.js基础02】fs、path模块

目录 一&#xff1a;fs模块-读写文件 1 加载fs模块对象 2 读制定文件内容文件 3 向文件中写入内容 二&#xff1a;path模块-路径处理 1 问题引入 2 __dirname内置变量 使用方法 一&#xff1a;fs模块-读写文件 fs模块封装了与本机文件系统交互方法和属性 1 加载fs模块…

弹性布局 flex layout HTML CSS

文章目录 效果图参考文档代码 效果图 其实弹性布局的好处是&#xff1a;当网页大小变化&#xff08;如窗口resize&#xff09;时&#xff0c;处于弹性容器(flex container)中的弹性元素(flex item) 之间的距离也会变化。 需要特别注意的是&#xff1a; 弹性布局的主要CSS如下。…

开源邮箱套件介绍系列2:Roundcube webmail

1. 项目介绍 项目网站&#xff1a;Roundcube – Free and Open Source Webmail Software Roundcube 项目是一个免费的开源网络邮件解决方案&#xff0c;具有类似桌面的用户界面&#xff08;Webmail&#xff09;&#xff0c;易于安装/配置&#xff0c;并且可以在标准的LAMPP服…

PostgreSQL 中如何处理数据的唯一性约束?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何处理数据的唯一性约束&#xff1f;一、什么是唯一性约束二、为什么要设置唯一性约束…

SAP第二季度财报和进一步裁员计划

7月22日公布了截至 2024 年 6 月 30 日的第二季度财务报告。以下位总体指标 当前云计算在手订单达 148 亿欧元&#xff0c;按名义货币和固定汇率计算均增长 28%云收入增长 25%&#xff0c;其中云 ERP 套件收入增长 33%&#xff0c;均按名义货币和固定汇率计算总收入增长 10%&a…

mysql 先子查询过滤再联合 和 先联合再过滤 执行效率问题

执行顺序 先子查询过滤再联合 SELECT XXX FROM(select * from edw_data_dyd.overrun_offsite_info WHERELENGTH( VEHICLE_ID ) > 12 AND CREATED_TIME > DATE_ADD(NOW(),INTERVAL -1 HOUR)AND CREATED_TIME < NOW()AND VEHICLE_ID not like %无车牌%AND VEHICLE_I…

Mac中maven配置安装路径

Mac中maven配置安装路径 没有下载maven的可以先下载&#xff1a;&#xff08;这里建议maven版本不要下高了&#xff09; 如果你的bash_profile中没有配置JAVA_HOME路径&#xff0c;可以按照下面的命令配置一下 获取JAVA的安装路径&#xff1a; /usr/libexec/java_home -V …

Pycharm2024最新版community社区版下载安装配置,快速上手

第一步&#xff1a;下载 方法1&#xff1a;官网链接 https://www.jetbrains.com/pycharm/download/?sectionwindows .方法2&#xff1a;百度网盘 链接&#xff1a;https://pan.baidu.com/s/1ic2N5hUQ2m1Kmyr5nK9Jxw?pwd76dt 提取码&#xff1a;76dt --来自百度网盘超级…

接口自动化测试框架实战-2-项目接口文档

上一小节我们完成了项目开发环境的搭建&#xff0c;本小结我们具体介绍一下项目中使用到的接口文档。 本次我们以钉钉开放接口作为项目接口测试的示例&#xff0c;方便大家都能统一学习和调用&#xff0c;具体接口如下&#xff1a; 1、获取企业内部应用的access_token 在获取…

poi库简单使用(java如何实现动态替换模板Word内容)

目录 Blue留言&#xff1a; Blue的推荐&#xff1a; 什么是poi库&#xff1f; 实现动态替换 第一步&#xff1a;依赖 第二步&#xff1a;实现word模板中替换文字 模板word&#xff1a; 通过以下代码&#xff1a;&#xff08;自己建一个类&#xff0c;随意取名&#xf…

(8) ubuntu ROS 安装

文章目录 安装流程1. 进入ros官网2. 根据自己ubuntu系统选择版本&#xff08;我是20.04的ubuntu&#xff09;3.根据流程开始安装3.1 设置sources.list 4.验证ros5.安装rosdep 安装流程 1. 进入ros官网 https://www.ros.org/ 2. 根据自己ubuntu系统选择版本&#xff08;我是2…

ORB_SLAM2 ORBSLAM2 Ubuntu20.04 ROS Noetic虚拟机镜像下载

下图是build.sh 和 build_ros.sh 编译完成截图&#xff1a; slam测试视频: orbslam2 ubuntu20.04 test 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16R7Pb6LjgR5SeoeBSZfgaQ?pwdu05r 提取码&#xff1a;u05r

【电源专题】结合锂电池相关资料和华为手机聊聊锂离子电池使用条件限制

在文章:【电源专题】锂电池的特点和工作原理 中我们讲到了一些关于锂电池种类和特点、工作原理等。但是对于锂离子电池使用条件限制却没有介绍,本文基于手机产商 锂离子电池使用条件-电池性能和应用介绍 | 华为官网 (huawei.com)提供的介绍文档再次深入学习锂离子电池的一些特…

FastAPI(六十七)实战开发《在线课程学习系统》接口开发--用户登陆接口开发

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 接上一篇文章FastAPI&#xff08;六十六&#xff09;实战开发《在线课程学习系统》接口开发--用户注册接口开发。这次我们分享实际开发--用户登陆接口…

面试知识储备-redis和redission

1.redis的使用 引入依赖&#xff0c;自动注解redistemplate即可使用&#xff0c; 默认的redistemplate存入到redis中是字符流的形式&#xff0c;需要配置redistemplate&#xff0c; 如果不想配置&#xff0c;可以使用stringRedistemplate 可以使用string类型&#xff0c;但是…

JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测

JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测 目录 JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现GA-Transformer-LSTM多变量回归预测&#xff0c;遗传优化算法&#…

书生大模型实战营闯关记录----第二关:实现word_count统计文本中word频次

实现word_count统计文本中word频次 请实现一个wordcount函数&#xff0c;统计英文字符串中每个单词出现的次数。返回一个字典&#xff0c;key为单词&#xff0c;value为对应单词出现的次数。 Eg: Input: """Hello world! This is an example. Word coun…

每日刷题记录(codetop版)

7.21 7.22 7.23 复习7.21和7.22

并发情况导致事务失效的场景

public void test(Pageable request){for (int i 0; i < 100; i) {//新建线程处理new Thread(() -> {userInfoService.testDemo();}).start();} } 这里创建多个线程模拟多并发场景 Transactional(rollbackOn Exception.class) public synchronized void testDemo() {…