编程基础系列--之--泛型基础,检索枚举,以及在抽象工厂中的使用

万丈高楼平地起,基础是重中之重,虽说基础在生产环境下作用并不大,但是扎实的基础是你不断学习的保障。今天继续探讨基础--泛型。

刚刚步入社会,开始自己的第一份工作,在工作中遇到这样一个业务场景:我需要将枚举字段存到数据库中,数据库是一位大佬设计的,枚举字段是英文,对应的值是int类型,我要在界面上显示的值却要是中文,这个问题其实并不难,按照我一开始的思路,我只需要根据数据库中存的值查询出来,必要的时候手动将英文转换成中文就可以了。但是在实际做项目的过程中才发现。这样设计的程序太死板而且特别麻烦。有没有好的解决方案呢?

答案是有的,枚举字段在定义的时候是可以设置一些文字描述的。我们可以将文字描述设置成中文,往数据库中存储的时候存它的中文描述就可以了,枚举字段起的作用就变成了强制用户选择时只能选这几个字段。而且后期如果需要添加新的选项,只需要修改枚举字段就可以了,代码是不需要改动的。

好了,说完了业务需求,步入今天的正题:泛型。

你可能会疑惑,说着说着枚举字段怎么会跳到泛型上去了?你Y的脑子有泡吧。不要着急,听我慢慢说

首先介绍一下泛型,引用一下官方定义:

1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)

2.在程序编码中一些包含参数的类。其参数可以代表类或对象等等。(人们大多把这称作模板)不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明

泛型很简单,就是我在定义的时候不知道你要给我传什么类型的值,所以我不设置具体的参数类型,你给我传什么我就用什么!!

下面用一些简单的java代码演示一下:

//定义一个泛型类
public class Generic <T>{
    public void show(T t)
    {
        System.out.println(t);
    }
}
//泛型类的使用
Generic<String> g1 = new Generic<String>();
g1.show("林青霞");
Generic<Integer> g2= new Generic<Integer>();
g2.show(30);
Generic<Boolean> g3=new Generic<Boolean>();
g3.show(true);

代码肯定会在某些地方看到过,思想都是一样的。我们的泛型类里面没有定义具体要打印的类型,只是有一个T作为要操作的类型,我们在实际使用的时候对这个类进行了一些初始化,传入了一个我们要操作的类型。运行一下就会发现,你传入什么类型值,函数打印的就是什么类型的值。我们如果不使用泛型,那么定义类的时候就有可能需要为每个类型定义一个重载函数才能实现我们现在要实现的这个小功能。

这就是基本的泛型。ok,说到这里简单的总结一下,泛型在我的理解里边是对操作的一种抽象和整理,操作大致相同的我们可以用一个泛型来处理,使用的时候只需要根据需求传不同的类型就可以了,降低了代码的冗余,提高了编码的效率。

ok。说完了简单的泛型介绍,我们来说一下怎么将枚举字段转换成list集合。下面的代码我将使用C#的编码规则,因为我本身是搞.net的,所以对C#语法比对Java要熟悉,再次强调,我是小白!!!

首先我们定义一个实体类,我们需要将从枚举中取出来的值放在实体类中,方便往前端界面传参

/// <summary>
        /// 枚举遍历实体内部类
        /// </summary>
        public class EnumberEntity
        {
            /// <summary>
            /// 枚举的描述
            /// </summary>
            public string Desction { get; set; }
            /// <summary>
            /// 枚举的名称
            /// </summary>
            public string EnumName { get; set; }
            /// <summary>
            /// 枚举对象的值
            /// </summary>
            public int EnvmValue { get; set; }
        }

接下来我们用泛型的思想,反射的方法来取枚举字段值,为什么要用泛型,因为我们要做的是一个可以被很多枚举使用的方法,而不知单独为这一个枚举写一个方法,如果单独为每一个枚举都写这样一个方法,代码冗余高,重用率不高,不是一个好的代码

public List<EnumberEntity> EnumToList<T>()
        {
            //思路很简单,定义一个内部实体类,将枚举中的值赋值到这个实体类中进行传参
            //实例化自定义的内部实体类
            List<EnumberEntity> list = new List<EnumberEntity>();
            //开始遍历要查询的枚举
            foreach (var e in Enum.GetValues(typeof(T)))
            {
                //实例化实体类
                EnumberEntity m = new EnumberEntity();

                object[] objArr = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true);//GetCustomAttributes这个方法是通过反射的方式来获取枚举的值,DescriptionAttribute:指定属性或事件的说明
                if (objArr != null && objArr.Length > 0)
                {
                    DescriptionAttribute da = objArr[0] as DescriptionAttribute;
                    m.Desction = da.Description;
                }
                m.EnvmValue = Convert.ToInt32(e);
                m.EnumName = e.ToString();
                //将查询出来的值加载到集合里面去
                list.Add(m);
            }
            return list;
        }

对,忘记说了,我的代码是基于MVC模式,这些代码是在控制器里写的。

对于这段代码我就不做详细的介绍了,思想蛮简单的

/// <summary>
        /// 测试枚举
        /// </summary>
        public enum Test
        {
            男=0,
            女=1
        }
        public ActionResult aaa()
        {
            EnumToList<Test>();

            return View();
        }

这是我在生产环境下做的写的一部分用到泛型的方法,接下来介绍一下我对设计模式的理解。下面的代码将不是生产模式下的代码,我的级别还不到可以管理整个项目,这里只是我自己闲着没事研究的。本着技术共享的原则,跟大家探讨一下。

首先说一下我对设计模式的理解:在我的理解中,设计模式是用来解耦的,所谓的解耦就是减少上层对底层的依赖,那么为什么要有解耦呢?因为懒。。。。。。。

想象一个场景,你刚做完一个需求,突然,产品经理跟你说要改需求,这里小小的改动一下,可能只是添加一个功能,但是因为你的代码对下层的依赖非常严重,你需要改上层表现层,甚至连底层的数据访问层都需要改,只是添加一个很简单的功能,却需要三层全部都需要改,是不是一件很可怕的事?

所以需要解耦~

而设计模式中最基本的就是对方法对模块进行抽象,如何抽象能检验一个程序员水平的高低。

今天先说一下我在学习过程中是怎么使用设计模式的思想进行重构项目的(自己领悟的,也不晓得这样使用对不对)。

首先在Dal层抽象一个工厂类

/// <summary>
    /// 抽象数据访问工厂类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class AbstractDalFactiry<T> where T:class
    {
        /// <summary>
        /// 抽象工厂中添加数据的抽象方法
        /// </summary>
        /// <param name="entity">要添加的实体类</param>
        /// <returns></returns>
        public abstract IAdd<T> Add();
        /// <summary>
        /// 抽象工厂中修改数据的抽象方法
        /// </summary>
        /// <param name="entity">要修改的实体类</param>
        /// <returns></returns>
        public abstract Ihandle<T> Update();
        /// <summary>
        /// 抽象工厂中删除数据的抽象方法
        /// </summary>
        /// <param name="entity">要删除的实体类</param>
        /// <returns></returns>
        public abstract Ihandle<T> Deleete();
        /// <summary>
        /// 抽象工厂中要查询的实体类
        /// </summary>
        /// <param name="entity">要查询的实体类</param>
        /// <returns></returns>
        public abstract SelectAccent<T> SelectAccent();

        /// <summary>
        /// 抽象工厂中保存数据库的修改
        /// </summary>
        /// <returns></returns>
        public abstract int SaveChange();
    }

接着写一个抽象工厂实现类

public class DALFactiry<T> : AbstractDalFactiry<T> where T : class
    {
        DbContext DB = new DbContextFactory().CreateDbContext();
        /// <summary>
        /// 添加,实例化添加类
        /// </summary>
        /// <returns></returns>
        public override IAdd<T> Add()
        {
            return new Add<T>(DB);
        }
        /// <summary>
        /// 删除,实例化删除类
        /// </summary>
        /// <returns></returns>
        public override Ihandle<T> Deleete()
        {
            return new Delete<T>(DB);
        }

        /// <summary>
        /// 查询,实例化查询类
        /// </summary>
        /// <returns></returns>
        public override SelectAccent<T> SelectAccent()
        {
            return new SelectAccent<T>(DB);
        }
        /// <summary>
        /// 修改,实例化修改类
        /// </summary>
        /// <returns></returns>
        public override Ihandle<T> Update()
        {
            return new Update<T>(DB);
        }

        /// <summary>
        /// 将更改保存到数据库
        /// </summary>
        /// <returns></returns>
        public override int SaveChange()
        {
            return DB.SaveChanges();
        }

    }

以查询为例

public class SelectAccent<T> where T:class
    {
        /// <summary>
        /// EF上下文对象
        /// </summary>
        readonly DbContext Db = null;

        public SelectAccent(DbContext db)
        {
            Db = db;
        }

        #region 查询
        /// <summary>
        /// 按照条件查询
        /// </summary>
        /// <typeparam name="Tkey">键,查询时按什么排序</typeparam>
        /// <param name="whereLambda">查询条件</param>
        /// <param name="orderby">排序条件</param>
        /// Expression,list使用这个会直接将linq表达式转换成树结构查询。
        /// <returns></returns>
        public IList<T> LoadEntites<Tkey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderby)
        {

            if (orderby==null)
            {
                return Db.Set<T>().Where(whereLambda).ToList();
            }
            return Db.Set<T>().Where(whereLambda).OrderBy(orderby).ToList();
        }

        /// <summary>
        /// 查询所有
        /// </summary>
        /// <returns></returns>
        public IList<T> LoadEntitiesAll()
        {
            return Db.Set<T>().ToList();
        }
        #endregion

        #region 分页查询
        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="key">排序键</typeparam>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">每页条数</param>
        /// <param name="paged">分页信息</param>
        /// <param name="whereLambda">条件</param>
        /// <param name="orderby">排序</param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public List<T> LoadPageEntities<key>(int pageIndex, int pageSize, out PagedInfo paged, Expression<Func<T, bool>> whereLambda, Expression<Func<T, key>> orderby, bool desc = true)
        {
            IQueryable<T> tmp;
            if (desc)
            {
                //降序排列
                tmp = Db.Set<T>().Where(whereLambda).OrderByDescending(orderby);
            }
            else
            {
                //升序排
                tmp = Db.Set<T>().Where(whereLambda).OrderBy(orderby);
            }

            //将分页信息进行封装到实体类中
            paged = new PagedInfo
            {
                TotalItems = tmp.Count(),
                CurrentPage = pageIndex,
                TotalPages = (tmp.Count() + pageIndex - 1) / pageSize
            };
            //跳过当前页数减一页条数据
            return tmp.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();

        }
        #endregion

    }

你会发现,其实很简单,无非就是定义了一个抽象类,一个实现工厂,之后工厂中封装了我的查询类中的泛型方法。在BAL层只需要调用这个工厂就可以了。这是我理解的泛型在抽象工厂模式中的使用

今天就先分享到这里了,持续学习,持续分享,欢迎各位大佬评论指导哦~

原文地址:https://www.cnblogs.com/Xiaomoml/p/11974329.html

时间: 2024-08-29 16:31:09

编程基础系列--之--泛型基础,检索枚举,以及在抽象工厂中的使用的相关文章

java夯实基础系列:泛型

一.概念 1.为什么需要泛型? 不使用泛型时: public class Test01 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("m1", "sssss"); String str = (String)map.get("m1"); } } 使用泛型后: public class Test01 { public static vo

《Java架构筑基》从Java基础讲起——泛型基础

一.泛型的概述 1.1 泛型由来 我们的集合可以存储多种数据类型的元素,那么在存储的时候没有任何问题,但是在获取元素,并向下转型的时候,可能会存在一个错误,而这个错误就是ClassCastException . 很显然,集合的这种可以存储多种数据类型的元素的这个特点,不怎么友好 , 程序存在一些安全隐患,那么为了出来这种安全隐患,我们应该限定一个集合存储元素的数据类型,我们只让他存储统一中数据类型的元素,那么在做向下转型的是就不会存在这种安全隐患了. 怎么限定集合只能给我存储同一种数据类型的元素

Linux基础系列之--Linux基础入门

1.Linux相关的开源协定有: GPL:General Public License(通用公共许可证) LGPL GPLv2 BSD: Apache (1).GPL: DPL是GNU General Public License的缩写,是GNU通用公共授权非正式的中文翻译.它并非由自由软件基金会所发表,亦非使用GNU通用公共授权的软件的法定发布条款─只有GNU通用公共授权英文原文的版本始具有此等效力. 详细信息参见链接:https://baike.baidu.com/item/GPL/2357

Java零基础系列002——命名、变量类型、类型转换、JDK中二进制整数和数字分隔符新特性

public class BasicDataType { public static void main(String[] args) { /* * 标示符:用于给变量.方法.类命名,必须以字母.下划线.$符号开头.以字母.下划线.数字.$符号组合,且不能为关键字 * * * */ System.out.println("--------------标示符------------"); int $,_,a;//正确的命名 int 彭驰=12;//由于Java内部采用Unicode编码方

C#基础系列——异步编程初探:async和await

前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了异步并行变成带来了很大的方便.异步编程涉及到的东西还是比较多,本篇还是先介绍下async和await的原理及简单实现. C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序列化效率比拼 C#基础系列——反射笔记 C#基础系列——At

夯实Java基础系列13:深入理解Java中的泛型

目录 泛型概述 一个栗子 特性 泛型的使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型方法总结 泛型上下边界 泛型常见面试题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star.Fork.Watch三连哈,感谢你的

C#基础系列——小话泛型

前言:前面两章介绍了C#的两个常用技术:C#基础系列——反射笔记 和 C#基础系列——Attribute特性使用 .这一章来总结下C#泛型技术的使用.据博主的使用经历,觉得泛型也是为了重用而生的,并且大部分时候会和反射一起使用.这次还是打算围绕WWH(即What.Why.How)来讲解. 1.什么是泛型:通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用.怎么理解呢,其实根据博主的理解,泛型就是将类型抽象化,使用抽象化的类型或对象去实现某些功能

C#基础系列——一场风花雪月的邂逅:接口和抽象类

前言:最近一个认识的朋友准备转行做编程,看他自己边看视频边学习,挺有干劲的.那天他问我接口和抽象类这两个东西,他说,既然它们如此相像, 我用抽象类就能解决的问题,又整个接口出来干嘛,这不是误导初学者吗.博主呵呵一笑,回想当初的自己,不也有此种疑惑么...今天打算针对他的问题,结合一个实际的使用场景来说明下抽象类和接口的异同,到底哪些情况需要用接口?又有哪些情况需要用抽象类呢? C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序

《Java 基础系列》初步整理

<Java 基础系列>初步整理大概有 12 篇,主要内容为.: 抽象类和接口内部类修饰符装箱拆箱注解反射泛型异常集合IO字符串其他第一篇我们来聊聊抽象类和接口. "抽象类和接口"听起来是非常普遍的东西,有些朋友会觉得:这个太基础了吧,有啥好说的,你又来糊弄我. 这里写图片描述 事实上我在面试中不仅一次被问到相关的问题: 抽象类和接口之间的区别?什么时候创建抽象类?什么时候创建接口?设计框架时该如何选择?我比较喜欢这样的问题,答案可深可浅,体现了我们对日常工作的思考. 我们什