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

news2024/11/15 7:33:18

这里写目录标题

  • 业务
    • 业务场景
    • 流程分析
  • 实现
    • 数据访问层(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.coloradmin.cn/o/1945071.html

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

相关文章

【N-MOS】N-mos(场效应管)驱动电路分析

目录 1、MOS管分类 2、MOS管导通原理 3、电路分析 源文件下载 可访问底部联系方式也可前往电子校园网官网搜索关键词 关键词&#xff1a;N-MOS 1、MOS管分类 MOS管是金属(metal)、氧化物(oxide)、半导体(semiconductor)场效应晶体管。FET是场效应管。合在一起是金属氧化物半导…

正则表达式与文本三剑客之grep

目录 前言 一、grep命令 二、基础正则表达式常见元字符 2.1、特殊字符 2.2、定位符 2.3、非打印字符 三、元字符操作实例 3.1、查找特定字符 3.2、利用中括号“[]”来查找集合字符 3.3、查找行首“^”与行尾字符“$” 3.4、查找任意一个字符“.”与重复字符“*” 3.…

ARM系列运行异常排查

一、断点指令BKPT BKPT指令产生软件断点中断,可用于程序的调试。它使处理器停止执行正常指令(使处理器中止预取指)而进入相应的调试程序。 BKPT指令的格式为:BKPT 16位的立即数 二、使用BKPT进行软件异常定位 假设异常发生后,全局变量k变成了88,现在想确认具体是什么…

【题解】UVA1564/SP2883 Widget Factory

题解 题意 题解分析Code 前言 调了好久&#xff0c;还是太菜了 题意 洛谷&#xff1a; SP UVA vjudge SP UVA 题解 分析 转换一下&#xff0c;题目就是让我们解方程组&#xff1a; { ∑ i 1 n a 1 , i x i ≡ b 1 ( m o d 7 ) ∑ i 1 n a 2 , i x i ≡ b 2 ( m o d 7 ) …

Java学习Day13:基础篇3

流程控制 1.if 案例&#xff1a; public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int a sc.nextInt();int b sc.nextInt();int c sc.nextInt();if (ab>c&&ac>b&&bc>a){System.out.println(&quo…

连锁店收银系统源码

系统概况&#xff1a; 专门为零售行业的连锁店量身打造的收银系统&#xff0c;适用于常规超市、生鲜超市、水果店、便利店、零食专卖店、服装店、母婴用品、农贸市场等类型的门店使用。同时线上线下数据打通&#xff0c;线下收银的数据与小程序私域商城中的数据完全同步&#…

06-Ubuntu 22.04LTS安装 Redis | QuickRedis 远程连接

文章目录 1. 安装命令2. 查看redis 状态3. 查看配置文件的位置4. 注释掉bind addr&#xff0c;并设置redis密码5. 设置端口6379开放6. 重启redis6. 本地测试连接7. QuickRedis 远程连接 1. 安装命令 sudo apt-get update sudo apt-get install redis-server2. 查看redis 状态 …

dsa加训

refs: OI Wiki - OI Wiki (oi-wiki.org) 1. 枚举 POJ 2811 熄灯问题 refs : OpenJudge - 2811:熄灯问题 如果要枚举每个灯开或者不开的情况&#xff0c;总计2^30种情况&#xff0c;显然T。 不过我们可以发现&#xff1a;若第i行的某个灯亮了&#xff0c;那么有且仅有第i行和第…

MQ传递用户信息

theme: nico 你们好&#xff0c;我是金金金。 场景 购物车里面有5个商品&#xff0c;用户勾选了并且提交订单了&#xff0c;此时需要删除购物车对应勾选的商品&#xff0c;mq的话涉及到传递用户信息~因为删除对应的购物车商品是需要传递用户信息来知晓对应用户的 生产者 消费者…

SolidWorks 二次开发--创建属性页面及控件事件(二)

在前文中我们学习了如何创建和显示属性页面&#xff0c;本章节将重点介绍如何向属性页面中添加控件。控件是属性页面的基本组成部分&#xff0c;可以是文本框、按钮、复选框等&#xff0c;用于用户交互和数据展示。接下来我们将看到如何定义、配置和操作这些控件&#xff0c;让…

ROS2入门到精通—— 2-8 ROS2实战:机器人安全通过狭窄区域的方案

0 前言 室内机器人需要具备适应性和灵活性&#xff0c;以便在狭窄的空间中进行安全、高效的导航。本文提供一些让机器人在狭窄区域安全通过的思路&#xff0c;希望帮助读者根据实际开发适当调整和扩展 1 Voronoi图 Voronoi图&#xff1a;根据给定的一组“种子点”&#xff0…

【保姆级介绍PyCharm安装教程】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 🤹目录 🤹前言🤹前提条件🤹安装步骤🤹前言 🥰PyChar…

外卖霸王餐系统架构怎么选?

在当今日益繁荣的外卖市场中&#xff0c;外卖霸王餐作为一种独特的营销策略&#xff0c;受到了众多商家的青睐。然而&#xff0c;要想成功实施外卖霸王餐活动&#xff0c;一个安全、稳定且高效的架构选择至关重要。本文将深入探讨外卖霸王餐架构的选择&#xff0c;以期为商家提…

仕考网:公务员考试申论答题技巧

在国家公务员考试的申论部分&#xff0c;要想取得好的成绩&#xff0c;关键在于掌握有效的写作方法。 1.文章结构 申论考试中&#xff0c;一个清晰、逻辑性强的结构是至关重要的。这种结构能迅速找到核心论点和支持论据。 2.紧贴主题 申论试题经常设置特定条件或要求&#…

谁说软考高级难?这个“通关秘籍”人人都能掌握

今天给大家分享一个非常有效的学习方法&#xff0c;来自网友的经验精华&#xff0c;仅供参考。 尝试了这个方法之后&#xff0c;你会觉得软考高级考试真的有点容易了&#xff01;想要及格拿证都是分分钟的事情&#xff01;按照我的方法&#xff0c;就算你从来没有考过初级和中级…

Python+Flask+Mysql or sqlite,搭建个人博客

昨天逛csdn看到了一个前端小框架界面&#xff0c;想着试着搭建一下要了一份源代码&#xff0c;因为我自己本身好久没有接触&#xff0c;好多知识有忘记了&#xff0c;只能重温python爬虫问题了&#xff0c;随后跟博主要了一份源码&#xff0c;作为练习使用&#xff0c;也不是很…

Java根据code获取枚举优化

Java枚举获取优化 需求原始解决方案优化方案1. 首先创建base接口。2. 创建枚举工具类3. 需要使用工具类的枚举&#xff0c;实现BaseEnum接口即可4. 测试使用 拓展 需求 自己模拟两个枚举&#xff0c;假设业务中需要用到 Example1StatusEnum.java package com.zdh.zdhenum;/*…

【大师与bug里特】M_Studio《王国之梦》学习笔记

1️⃣ Object & object(✅) 之辨 《7.泛型事件框架〈余2min左右时〉》 不然inspector窗口的最后一行&#xff08;告诉我们订阅者是SceneLoadManager它身上挂了☝️ObjectEventListener用来监听这个事件 有多少个事件注册到这里来了都能够看到&#xff09;还是不会出现 加上…

光谱分析仪进行一些常规参数测量的方法有哪些?

光谱分析仪在光纤通信产品中的应用&#xff0c;以AQ6370光谱分析仪为例&#xff0c;详细说明了使用光谱分析仪进行一些常规参数测量的方法。这些参数包括光谱的带宽、边模抑制比、增益、噪声系数和系统OSNR等。文章中还提到了光谱分析仪的一些基本功能&#xff0c;如屏幕显示测…

人大金仓亮相国际金融展,助力数字金融跑出“加速度”

7月19日至21日&#xff0c;由商务部批准、中国金融电子化集团有限公司主办的2024中国国际金融展&#xff08;以下简称“金融展”&#xff09;在北京国家会议中心举办。作为数据库领域国家队&#xff0c;人大金仓携金融领域创新成果与解决方案亮相本次金融展&#xff0c;获得了业…