zoukankan      html  css  js  c++  java
  • C#多态“说来也说”——逻辑层BLL中的多态使用

    本文版权归博客园和作者吴双本人共同所有。欢迎转载,转载和爬虫请注明原文地址  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层当中。

    1   public class UserDal: BaseDal<UserEntity>
    2   {
    3         
    4   }
    1   public class AdminDal: BaseDal<AdminEntity>
    2     {
    3         public void Manage()
    4         {
    5             Console.WriteLine("管理员管理网站");
    6         }
    7     }
     1 public class BaseDal<T>
     2     {
     3         public void AddObj(T obj)
     4         {
     5             Console.WriteLine("添加对象成功,对象属于"+obj.GetType().ToString());
     6         }
     7 
     8         public void DeleteObj(T obj)
     9         {
    10             Console.WriteLine("删除对象成功,对象属于"+obj.GetType().ToString());
    11         }
    12 
    13     }

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

     1  public class UserBll 
     2     {
     3         UserDal dal = new UserDal();
     4 
     5         public void Add(UserEntity obj)
     6         {
     7             dal.AddObj(obj);
     8         }
     9 
    10         public void Delete(UserEntity obj)
    11         {
    12             dal.DeleteObj(obj);
    13         }
    14      }
        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对象设置实际的值。我先给出子类的代码

     1 public class AdminBll : BaseBll<AdminEntity>
     2     {
     3         AdminDal dal = new AdminDal();
     4         public AdminBll()
     5         {
     6 
     7         }
     8         public void Manage()
     9         {
    10             new AdminDal().Manage();
    11         }
    12 
    13         public override void SetCurrentDal()
    14         {
    15             currentDal = new AdminDal();
    16         }
    17     }
    1 public class UserBll : BaseBll<UserEntity>
    2     {
    3         public override void SetCurrentDal()
    4         {
    5             base.currentDal = new UserDal();
    6         }
    7     }

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

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

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             AdminBll adminBll = new AdminBll();
     6             AdminEntity admin = new AdminEntity() {AdminName="吴双",AdminPwd="123" };
     7             adminBll.Manage();
     8             adminBll.BaseAdd(admin);
     9             Console.ReadKey();
    10         }
    11     }

    输出结果:

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

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

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

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

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

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

  • 相关阅读:
    Junit单元测试
    win7的6个网络命令
    WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS
    WOJ1022 Competition of Programming 贪心 WOJ1023 Division dp
    woj1019 Curriculum Schedule 输入输出 woj1020 Adjacent Difference 排序
    woj1018(HDU4384)KING KONG 循环群
    woj1016 cherry blossom woj1017 Billiard ball 几何
    woj1013 Barcelet 字符串 woj1014 Doraemon's Flashlight 几何
    woj1012 Thingk and Count DP好题
    woj1010 alternate sum 数学 woj1011 Finding Teamates 数学
  • 原文地址:https://www.cnblogs.com/tdws/p/5861842.html
Copyright © 2011-2022 走看看