走向.NET架构设计—第五章—业务层模式,原则,实践(前篇)

发布时间:2026/7/5 2:33:12
走向.NET架构设计—第五章—业务层模式,原则,实践(前篇) 在上一章中我们讲述了有关业务层分层的一些知识下面我们就来看看在具体的业务层的设计中我们可以采用哪些模式可以将业务层设计的更加的灵活架构模式首先我们就来看看如何更加有效的组织业务规则。Specification Pattern(需求规格模式)这个模式的使用方法就是把业务规则放在业务类的外面并且封装成为一个个返回boolean值的算法。这些一个个的业务规则的算法不仅仅便于管理和维护并且还可以被重用而且很方便的组织成为复杂的业务逻辑。下面我们就来看一个以在线租DVD的公司的例子。例子很简单场景也很简单判断一个用户是否可以租更多的DVD。下面就是我们设计的一个基本的类图。大家肯定觉得一上来就看类图有点突兀没有一步步的分析其实我是想让大家知道所讲的是个什么东西样子之后大家再慢慢的理解下面我们就开始做这个事情public interface ISpecificationT{bool IsSatisfiedBy(T entity);}public class HasReachedMaxSpecification : ISpecificationCustomer{public bool IsSatisfiedBy(Customer entity){return entity.TotalRentNumber 5;}}上面的代码其实就是把一个个的业务规则抽象出来了。我们知道在系统中不管业务规则多么复杂最后在进行业务逻辑判定的时候最后的结果还是“是否通过”。所以在这里就进行了抽象。因为我们的例子是以一个在线租赁DVD为例子用户可以来租赁DVD其中也是有一定的规则的例如如果用户已经租了3盘DVD那么我们就会考虑这个用户时候还可以继续租DVD。至于根据什么判断可能DVD公司规定一个人最多不能超过5盘或者DVD公司认为某个用户的信誉不好等等。下面我们就来定义个具体的业务规则HasReachedRentalThresholdSpecification根据这个规则就决定一个用户是否可以租DVD。代码这个规则定义出来后我们就在业务类中使用这个规则代码当然我们可以把更多的业务规则组合进来。这个例子到这里就完了这个例子中只是简单的采用了Specifiction模式。但是实际的情况往往是没有这个简单的因为一个业务逻辑往往要组合多个多个业务规则。下面我们就来进一步的看如果采用链式的结构来完成复杂的业务逻辑。Composite Pattern组合模式注这个模式不属于架构模式而且GOF模式的一种这里列出来主要是为了配合之前的Specification模式的大家不要在这里纠结这个问题 JComposite模式允许把一个集合对象当做单个的对象来使用而且我们还可以在这个所谓的”单个对象”中不断的嵌套。采用这种模式可以把对象的层级关系组合成为“树形”的结构我个人喜欢把它称为“容器模式”。其实这个模式在我们在平时的ASP.NET或者WinForm ,WPF中到处可见。例如一个Panel控件可以在里面加入另一个Panel,然后在Panel中可以加入GroupBox然后再GroupBox中还可以加入Button等控件。这就是.NET Framework设计中采用了Compiste模式的例子。下面来看看Compiste模式的UML结构图在上面的图中1. Component是一个抽象类这个类提供了一个Add方法这个Add可以加入其他的Component.大家想想这样是否就可以很容易的实现链式的效果。2. Leaf就是一个继承Component的具体类。看到上面图其实大家也可以想想在ASP.NET页面的生命周期中到处都是这种例子例如在ASP.NET页面的Init事件中因为Page本身就是一个容器这个容器里面包含了很多的其他的控件如Panel,Button而且Panel里面还是控件。那么在Init方法就会调用自己的子容器的Init方法然后子容器在调用自己的子容器的Init方法这样就层层调用直到最后调用到某个控件的Init的方法。这样这个页面的初始化就完成了。和上面的UML的结构是一样的。下面我们还是来看一个例子吧。继续之前的Specification模式的讨论看看如果结合则两种模式来组织复杂的业务逻辑。为了使得例子有点说服力我们把之前的业务稍微的变复杂一点点为了判定一个用户是否可以租DVD我们要进行一系列的规则判定之后才能决定结果1 用户的账号是否处于激活的状态2 用户之前是否还欠费3 用户租赁DVD的数量是否达到了规定的数量下面首先总体来看看一些类图的结构:不知道大家有没有注意一点每次我在讲述一个功能的时候总是先让大家看看总体的类图的设计然后再开始一个个的讲述。其实这样做事有原因的。在之前的文章中一直提到“设计Design”。就是说在做一个功能之前不是一下子就砸进去编码而是首先把功能考虑清楚然后从总体上考虑功能如何实现然后写出一些测试代码最后写出一些实现代码的骨架。上面的类图其实就是一个骨架。按照之前的Specification模式的例子我们首先条件两个类来新增的封装业务规则现在我们将例子进行扩充为了判定一个用户是否可以租DVD我们要进行一系列的规则判定q 用户的账号是否处于激活的状态。q 用户之前是否还欠费。q 用户租赁DVD的数量是否达到了规定的数量。代码上面的代码用来判断用户是否处于激活状态代码上面的代码就判断用户是否欠费添加完了所有的业务规则之后好戏就开始了。我们要把这些业务规则组合起来放在容器中然后只要调用父容器的一个方法规则验证就一层层进行下去就像我们之前举的ASP.NET的Init事件一样。首先我们来添加一个表示容器的类代码上面的代码有些不明白的地方没什么咱们耐心的往下面走。代码代码上面基础代码完成了我们就开始实现我们想要的链式的效果我们修改之前的几个规则和接口的定义如下代码漫长的过程终于结束了到了核心的部分请看业务类现在的定义public class Customer{private ISpecificationCustomer hasReachedRentalThreshold;private ISpecificationCustomer customerIsActive;private ISpecificationCustomer customerHasLateFees;public Customer(){hasReachedRentalThreshold new HasReachedMaxSpecification();customerIsActive new CustomerAvtiveSpecification();customerHasLateFees new CustomerHasLateFeesSpecification();}public decimal TotalRentNumber { get; set; }public bool IsActive { get; set; }public decimal LateFees { get; set; }public bool CanRent(){ISpecificationCustomercanRent customerIsActive.And(hasReachedRentalThreshold.Not()).And(customerHasLateFees.Not());return canRent.IsSatisfiedBy(this);}}大家主要看看那个 CanRent方法下面我们就来讲讲这个方法。customerAccountActive继承自CompositeSpecification,而Add方法的定义如下public ISpecificationT And(ISpecificationT other){return new AndSpecificationT(this, other);}_customerAccountIsActive.And(_hasReachedRentalThreshold.Not())的结果就是使得customerAccountIsActive内部包含了平行的两条业务规则结构如下方法返回的结果还是一个实现了ISpecification的对象只不过这个对象我们称之为“容器A”里面有两个规则了。然后这个保量两个业务规则的对象容器A再次调用Add方法如下_customerAccountIsActive.And(_hasReachedRentalThreshold.Not()).And(_customerAccountHasLateFees.Not());此时相当于把之前那个容器A作为一个单独对象再次调用Add方法于是这个三个规则组合成为一个大的规则的容器如下。今天就到这里东西不多大家多琢磨一下