C#多态“说来也说”——逻辑层BLL中的多态使用

时间:2022-05-01 03:21:38

本文版权归博客园和作者吴双本人共同所有。欢迎转载,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/5861842.html

昨天晚上,有个朋友说学了好久,依然没搞懂多态,让我简单讲解一下。我觉得多态在面向多想的三大特性当中,算是最简单的,最难的是看似容易的封装。在编写面向对象代码时,如何让代码可读性更强,除了变量和方法命名标准外,要做的到一个方法只做一件事情,这样的思想是《代码整洁之道》一书中主要推崇的思想,其实有经验的各位都希望自己看到的代码是简短,可维护,可读性强的,相信大家也都“有幸”遇到过几百上千行的代码,更过分的是有个朋友曾经维护一个上万行的Action,夸张的说,调试并走通逻辑,一次要三天,有的人说这是业务逻辑不断增加所导致,但我认为,在这种情况下,更应该尽量做到一个方法做一件事情。我也不多吐槽了,关于代码整洁,我在大三的时候,就"吐槽"过http://www.cnblogs.com/tdws/p/4674489.html

封装也不是今天的主题,今天我们要说的是多态,在朋友问我的时候,我给他举了下面这个简短的例子。

总体概括这个例子来讲就是在基本的三层架构当中,DAL层建两个类AdminDal,UserDal。两个类中,都有增加对象和删除对象地方法,那这个时候,我们应该给两个类抽象出一个父类BaseDal<T>,父类中是他们的公共方法,并且父类需要一个泛型T,这样父类的方法,才能明白你所要添加或者删除的object到底是什么类型的。请看如下代码。虽然两个类的公共方法在父类当中,但是他们自身特有的方法,还是要写在自己的Dal层当中。

   public class UserDal: BaseDal<UserEntity>
{ }
   public class AdminDal: BaseDal<AdminEntity>
{
public void Manage()
{
Console.WriteLine("管理员管理网站");
}
}
 public class BaseDal<T>
{
public void AddObj(T obj)
{
Console.WriteLine("添加对象成功,对象属于"+obj.GetType().ToString());
} public void DeleteObj(T obj)
{
Console.WriteLine("删除对象成功,对象属于"+obj.GetType().ToString());
} }

下面给出逻辑层代码,如果说普通的开发过程当中,你的代码也许是这样的。

  public class UserBll
{
UserDal dal = new UserDal(); public void Add(UserEntity obj)
{
dal.AddObj(obj);
} public void Delete(UserEntity obj)
{
dal.DeleteObj(obj);
}
}
    public class AdminBll 
{
AdminDal dal = new AdminDal(); public void Add(AdminEntity admin)
{
dal.AddObj(admin);
}
public void Delete(AdminEntity admin)
{
dal.DeleteObj(admin);
} public void Manage()
{
dal.Manage();
}
}

也就是在各自的逻辑层当中,调用dal层。这个时候你又看到依然有这么多重复的代码,是不是应该再次封装成一个BaseBll<T>呢。答案是肯定的,但是问题又来了,在封装父类的过程中,你会发现,这个dal的对象怎么封装呢?这就是用到多态的关键点。下面看一下BaseBll.cs的代码。

 public abstract class BaseBll<T> where T:class, new()
{
public BaseDal<T> currentDal; public BaseBll()
{
SetCurrentDal();
} public abstract void SetCurrentDal(); public void BaseAdd(T obj)
{
currentDal.AddObj(obj);
} public void BaseDelete(T obj)
{
currentDal.DeleteObj(obj);
} }

我给了一个抽象的基类,并且给出抽象的SetCurrentDal的抽象方法定义。该方法用于设置当前类的currentDal到底是adminDal还是userDal。我们在构造函数中调用SetCurrentDal这个抽象方法,为什么在构造函数中调用的原因是,当实例化子类对象时,一定是首先进入其父类的构造函数。当子类AdminBll和UserBll继承BaseBll<T>的时候,必须重写抽象方法,并且为BaseDal<T> currentDal对象设置实际的值。我先给出子类的代码

 public class AdminBll : BaseBll<AdminEntity>
{
AdminDal dal = new AdminDal();
public AdminBll()
{ }
public void Manage()
{
new AdminDal().Manage();
} public override void SetCurrentDal()
{
currentDal = new AdminDal();
}
}
 public class UserBll : BaseBll<UserEntity>
{
public override void SetCurrentDal()
{
base.currentDal = new UserDal();
}
}

当实例化子类的对象时,过程为:子类构造函数(不进入)—进入父类构造函数—父类构造内部调用子类重写的SetCurrentDal(当前多态的currentDal到底是谁的实例)—父类构造执行完毕(设置currentDal完成)—子类构造函数。这就是抽象方法实现的多态。

下面在UI层调用一下,看看结果:

     class Program
{
static void Main(string[] args)
{
AdminBll adminBll = new AdminBll();
AdminEntity admin = new AdminEntity() {AdminName="吴双",AdminPwd="" };
adminBll.Manage();
adminBll.BaseAdd(admin);
Console.ReadKey();
}
}

输出结果:

C#多态“说来也说”——逻辑层BLL中的多态使用

在开发的过程中,也许你会有很多实体类,每个实体类都有各自的增删改查等其他共有方法,基于这样的情况,我们就需要手段来将其封装。为什么在逻辑层使用了多态,原因就是我们封装父类的时候,不确定当前的currentDal到底是adminDal还是userDal还是xxxDal。为了封装出基类,这个多态的对象就必不可少了。

当然在实际当中,如果你是写原生sql,这样封装的确不容易,各种拼接sql。但如果说你用ORM框架,EF,Dapper之类的,这个方法真的是必不可少的,你可能再加上接口层,加上工作单元,创建对象非new,使用抽象工厂,依赖注入等。无论怎样,这一层的多态一定能用到,只是创建对象稍作修改。

下一阶段也打算进行后台架构搭建分享,MVC WebApi+EF/Dapper+工作单元+抽象工厂/依赖注入Autofac+AutoMapper+日志组件等。

我也曾多次在项目中搭建此类框架,在缓存提高性能,处理高并发,应用服务器集群,缓存集群,队列集群等方面,本次也会加入到分享当中。

如果今天的点滴分享,对您有点滴帮助,请点赞支持,也为自己的进步点赞。

点击下方关注,我们共同进步。

C#多态“说来也说”——逻辑层BLL中的多态使用的更多相关文章

  1. MVC&plus;Ef项目&lpar;4&rpar; 抽象业务逻辑层BLL层

    接下来,我们就要到业务逻辑层了,简单的说,业务逻辑层就是调用Repository(可以看做是DAL数据库访问层) 先来看看项目的架构 我们现在就开始来做BLL层.  同样,先编写  UserInfoS ...

  2. 微信小程序-06-详解介绍&period;js 逻辑层文件-注册页面

    上一篇介绍的是 app.js 逻辑层文件中注册程序,对应的每个分页面都会有的 js 文件中 page() 函数注册页面 微信小程序-06-详解介绍.js 逻辑层文件-注册页面 宝典官方文档: http ...

  3. java中实现多态的机制是什么&quest;

    多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次 ...

  4. ASP&period;NET MVC&plus;EF框架&plus;EasyUI实现权限管理系列&lpar;4&rpar;-业务逻辑层的封装

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(4)-业务逻辑层的封装 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2) ...

  5. 从零开始编写自己的C&num;框架(13)——T4模板在逻辑层中的应用(二)

    最近这段时间特忙,公事私事,忙得有时都没时间打开电脑了,这两周只能尽量更新,以后再将章节补回来. 直接进入主题,通过上一章节,大家明白了怎么使用模板类编写T4模板,本章进的是一些简单技巧的应用 1.首 ...

  6. 【C&num;&vert;&period;NET】从细节出发(三) 逻辑层事务和page object模式

    一. 业务逻辑层的事务问题 如果你的程序分层清晰并且系统禁用复杂存储过程,那么在DA中的职责比较单一.程序的逻辑通过BLL调用各种不同模块的DA来实现数据操作.如果当需要不同模块在一个事务的时候,问题 ...

  7. 一个项目中说系统分为表现层、控制层、逻辑层、DAO层和最终数据库五层架构-转

    表现层就是看到的东西,比如你现在看到的当前页面控制层就将你的请求从页面传到后台代码逻辑层就是处理你的请求的代码DAO层就是将数据存到数据库中的代码数据库就是数据库了,存东西用的 ,DAO层就是将访问数 ...

  8. C&num; &period;NET 逻辑层的框架设计

    前述:在我的了解中,一个大项目的逻辑层是不可捉摸的,对于不同项目或场景都是不同的逻辑.先说明,我的想法是对逻辑层类结构,以及如何操作逻辑的方法进行抽象的封装.并且考虑将不同类,或者不同程序集中的逻辑方 ...

  9. 架构-层-BLL:BLL

    ylbtech-架构-层-BLL:BLL 业务逻辑层(Business Logic Layer)无疑是系统架构中体现核心价值的部分.它的关注点主要集中在业务规则的制定.业务流程的实现等与业务需求有关的 ...

随机推荐

  1. js获取给定月份的N个月后的日期

    1.在讲js获取给定月份的N个月后的日期之前,小颖先给大家讲下getFullYear().getYear()的区别. ①getYear() var d = new Date() console.log ...

  2. Mac OS系统

    Mac OS系统 目录 概述 Mac OS系统常用操作 概述 Mac OS系统常用操作 显示或隐藏文件 在终端输入:defaults write com.apple.finder AppleShowA ...

  3. C&plus;&plus;:运算符重载函数之&quot&semi;&plus;&plus;&quot&semi;、&quot&semi;--&quot&semi;、&quot&semi;&lbrack; &rsqb;&quot&semi;、&quot&semi;&equals;&equals;&quot&semi;的应用

    5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++ ...

  4. SQL Mon 介绍

    原文:SQL Mon 介绍 这是一个相当高级的SQL Server监控工具,全面监控SQL Server的活动与性能,分析性能瓶颈,给出优化建议. red-gate有一个在线的数据库监控工具,不过那个 ...

  5. 谈谈渲染,玩玩nginx——前后端分离,转发请求到Tomcat的尝试

    一.谈谈"渲染" 相信好多人都挺听过"渲染"这个词,但不清楚它是什么意思?前端开发以为这是后端的活儿,后端开发以为是前端的事儿,推着推着就不了了之.其实渲染很简 ...

  6. Unity塔防游戏开发

    Unity3D塔防开发流程 配置环境及场景搭建编程语言:C#,略懂些许设计模式,如果不了解设计模式,BUG More开发工具:Unity3D编辑器.Visual Studio编译器开发建议:了解Uni ...

  7. Python核心编程--浅拷贝与深拷贝

    一.问题引出浅拷贝 首先看下面代码的执行情况: a = [1, 2, 3] print('a = %s' % a) # a = [1, 2, 3] b = a print('b = %s' % b) ...

  8. django-auth组件

    auth组件 一.auth模块简介 auth模块是django自带的用户认证模块,包含了身份验证和权限管理两部分. 身份验证用于核实某个用户是否合法,权限管理用于决定一个合法用户有哪些权限 默认情况下 ...

  9. P2016 战略游戏

    传送门 思路: 前置知识——普通树D: ▲普通的树形 DP : 设 f [ i ][ 0 ] 表示这个点不取,则它的所有子节点都要取:f [ i ][ 1 ] 表示这个点取,则它的子节点取与不取对之前 ...

  10. &lbrack;转载&rsqb; 相机越贵画质越好?聊聊CMOS设计

    似乎在很多人心目中,个位数机身就代表了品牌最强成像素质,这或许有“人不识货钱识货”的道理在作祟,但事实上如佳能1DX2或尼康D5,又或是索尼A9这种旗舰机真的就一定能代表本家的画质巅峰么?这一切都得从 ...