【分享】如何设计更加“面向对象”的三层架构系统(1)

摘要

  使用.Net开发的朋友,对于三层(N层)架构一定都不陌生,相信许多朋友也都曾细细研究过Duwamish/PetShop等经典案例。

  采用分层的方式对系统进行设计和架构,也的确可以提升系统的可维护性、扩展性。不过三层架构其实只是系统的一种设计思想,为系统的设计、开发提供了一种新的思路,与其相关的Duwamish/PetShop等案例也应只被当成“案例”或“示例”,而不应作为“标准”或“模板”。

  笔者并不认为三层架构有什么不好,但看到了太多的Duwamish/PetShop式的系统,基本是在照抄这些案例,而忽略了自身系统实际是否需要进行这样的设计。所以撰写此文,与大家一起探讨三层架构系统设计的一些技巧。

 

案例

  就以“员工管理”为例吧,我们要求也很简单:系统中的“员工信息”和“部门信息”两个对象,数据库中有“Employee”和“Department”两张表,相关对象的属性定义如下:

  员工信息(Employee): 自动编号,员工编号,真实姓名,性别,联系电话,所属部门,入职日期,备注

  部门信息(Department): 自动编号,部门名称,经理姓名,年假基准天数,备注

 

  要求:

  建立两个功能模块分别实现“员工信息”和“部门信息”的增删改查,其中“员工信息”对象要求:

    1. “所属部门”在界面上显示为汉字的“用户组名称”、数据库中存为整型的编号;

    2. “性别”在界面上显示为“男/女”、数据库中存为整型的“1/2”;

    3. “所属部门”与“性别”在编辑界面使用“下拉框”进行选择;

    4. 在查看员工的详细信息时,可以显示员工的当前可享受的年假天数,公式为:年假天数 = 部门年假基准天数+工作年限*1

 

实现

  我们以传统的三层架构设计思想,先来分析和设计这个案例。首先,我们可以先建立一个Visual Studio解决方案,可以是一个多项目的解决方案,也可以是一个单项目的解决方案,如下图:

【分享】如何设计更加“面向对象”的三层架构系统(1)_第1张图片

 

  系统如何分层、层的数量,应根据系统的实际需求和应用场景来决定,而不应当生搬硬套。本案例中我们建立了5个层,之后我们可以针对相关的功能要求,设计出“员工信息”和“部门信息”两个类,并定义数据库中的相关表结构,如下图:

【分享】如何设计更加“面向对象”的三层架构系统(1)_第2张图片

 

  然后,我们可以为所设计的对象,编写数据实体层、业务逻辑层、数据访问层的代码 。其中数据访问层至少就包含:Insert、Update、Delete、GetDataById、GetAllList、GetPageList等方法,用于实现两个对象的增删改查和分页功能。为了实现“员工信息”在界面上显示部门名称和性别,而不是数据表里所存储的数字,我们可以将数据访问层的相关方法进行改写,通过级联查询和条件判断,根据编号获取相应的名称,并为Employee.SexName和Employee.DepartName两个string类型属性赋值。当然也可以通过在“员工信息”类数据访问层中,直接调用“部门信息”类数据访问层中的GetDataById方法来获取,而不使用级联查询。

  业务逻辑层也应编写相关方法供用户界面层调用,有的朋友可能会觉得这个业务逻辑层似乎是多余的,其实不然。这是因为我们案例中的业务很简单,目前仅需增加一个CheckValid方法,用于对界面层传入的对象进行有效性检查。为了实现“在界面显示员工的当前可享受的年假天数”这一功能,我们可以再在业务逻辑层中增加一个GetVacationDays方法,用于根据员工的入职日期、所在部门、部门年假基准天数来进行计算。

  最后,开始设计系统的界面,并将相关界面文件放到用户界面层中去。在员工信息列表界面中,我们可以指定数据控件中的“性别”、“所属部门”2列,分别与员工对象中的“性别显示名称”、“部门显示名称”进行绑定。在员工信息编辑界面中,指定“性别”下拉框的可选项、指定“所属部门”下拉框的DataSource=DepartmentBLL.GetAllList(),如下图:

【分享】如何设计更加“面向对象”的三层架构系统(1)_第3张图片

 

  为了实现“可以查看员工的当前可享受的年假天数”这一功能,我们可以在“查看详细”页面中,通增加一个Lable控件,并在后台指定其Text属性为:EmployeeBLL.GetVacationDays().ToString()来实现。至此,我们已经完成了一个三层框架系统的设计,并基本实现了相关的功能要求。

 

改进

  在我们完成了系统的设计工作后,请考虑针对“员工信息类”的以下功能变更:

      1.增加一个“所学专业”属性,所学专业需要存储于数据库并可以维护;

    2.增加一个“政治面貌”属性,其值固定为团员、党员、群众、九三学社;

    3.修改年假天数的算法,实现“性别”为女的员工,在现有算法基础上自动加1天。

  稍加分析我们可以发现:员工信息类会随着关联对象的增多,而增加越来越多仅用于显示的冗余属性;“性别”、“政治面貌”这类存储于数据库显得浪费,直接在代码中进行硬编码又存在难以维护的问题,如果这类属性牵涉到业务方法,由于不能“自解释”本身的含义,业务代码也会别的晦涩难懂,虽然使用“枚举”类型可以缓解该问题,但是又存在与界面控件绑定不方便等问题。另外,还存在得到一个员工对象实例,仍需根据编号再次进行数据访问,才能获得关联的“所属部门”、“所学专业”等关联对象的完整信息,如果业务复杂的话,会增加大量的数据访问交互。

 

  所以我们可以做出如下调整:删除“员工信息类”中所有仅用于显示的属性,如“性别显示名称”、“部门显示名称”,增加一个添的“Sex性别”类到数据实体层,修改员工类中“性别”和“所属部门”2个属性的类型,由string分别改为SexDepartment,也就是直接在员工类中引用“性别”和“部门”类作为其属性。并增加一个只有get方法的属性VacationDays,用于直接计算并获取员工实例的年假天数,使外界调用更为直观。调整后的“员工信息类”的属性定义,如下图:

【分享】如何设计更加“面向对象”的三层架构系统(1)_第4张图片

 

   其中Sex类中的代码如下:

View Code

    其中员工信息类中VacationDays属性的代码如下:

View Code

    我们再对“员工信息类”的数据访问层代码进行相关改写,如:

View Code

     然后,我们再对“员工信息类”的业务逻辑层,有效性检查代码进行相关改写,如:

View Code

    最后,我们可以调整相关界面的数据绑定方法,因为我们重写了Sex和Department类的ToString()方法,所以可以直接将其绑定给界面显示控件。

    通过如上改进,我们可以发现:系统的设计变的更加符合面向对象的特性;系统中的代码不但增加了可读性,而且数量也减少了许多;更关键的是系统可扩展性、可维护性也都得到了加强。关于三层架构的其它设计技巧,我也将陆续撰写一些系列文章与大家一起分享,感兴趣的朋友可以关注我的博客。

 

    撰写本文时,笔者使用了自己所开发EasyCode .Net代码生成器,对案例进行了设计和生成。如果您想了解EasyCode的详细信息,请您单击下面的链接:

       http://www.cnblogs.com/BudEasyCode/archive/2012/02/27/2370549.html

       如果您需要本案例的源码,请从下面的链接下载:

       http://files.cnblogs.com/BudEasyCode/NTier.rar

 http://www.cnblogs.com/BudEasyCode/archive/2012/03/03/2378227.html

你可能感兴趣的:(面向对象)