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

简介:
走向.NET 架构设计 第五章 业务层模式,原则,实践(前篇)
  前言:不管是GOF 23 种设计模式,还是Flower 的企业架构模式,相信很多的朋友知道或者听说过。在那些很经典的书中,对模式都做了很精辟的解释,本篇的目的在于看看这些模式如何应用在项目中的,并且给出一些代码的例子,小洋也希望大家能够真正的理解这些模式的思想,而不仅仅停留在代码结构和表面上。
  
本篇的议题如下:
架构模式
设计模式
设计原则
 
  
  在上一章中,我们讲述了有关业务层分层的一些知识,下面我们就来看看,在具体的业务层的设计中,我们可以采用哪些模式可以将业务层设计的更加的灵活!
 
  架构模式
  首先我们就来看看,如何更加有效的组织业务规则。
 
  Specification Pattern( 需求规格模式)
 
  这个模式的使用方法就是:把业务规则放在业务类的外面,并且封装成为一个个返回 boolean 值的算法。这些一个个的业务规则的算法不仅仅便于管理和维护,并且还可以被重用,而且很方便的组织成为复杂的业务逻辑。
 
  下面我们就来看一个以在线租 DVD 的公司的例子。例子很简单,场景也很简单:判断一个用户是否可以租更多的 DVD 。下面就是我们设计的一个基本的类图。(大家肯定觉得一上来就看类图有点突兀,没有一步步的分析,其实我是想让大家知道,所讲的是个什么东西样子,之后大家再慢慢的理解)
下面我们就开始做这个事情:
  public  interface ISpecification<T>
    {
         bool IsSatisfiedBy(T entity); 
    }

     public  class HasReachedMaxSpecification : ISpecification<Customer>
{
         public  bool IsSatisfiedBy(Customer entity)
        {
             return entity.TotalRentNumber >  5;
        }
}
 
    上面的代码,其实就是把一个个的业务规则抽象出来了。我们知道,在系统中,不管业务规则多么复杂,最后在进行业务逻辑判定的时候,最后的结果还是“是否通过”。所以在这里就进行了抽象。
 
  因为我们的例子是以一个在线租赁 DVD 为例子,用户可以来租赁 DVD ,其中也是有一定的规则的,例如,如果用户已经租了3 DVD ,那么我们就会考虑,这个用户时候还可以继续租 DVD 。至于根据什么判断:可能 DVD 公司规定一个人最多不能超过 5 盘,或者 DVD 公司认为某个用户的信誉不好等等。 
  下面我们就来定义个具体的业务规则: HasReachedRentalThresholdSpecification
  根据这个规则就决定一个用户是否可以租 DVD    
 
代码
  public   class  HasReachedRentalThresholdSpecification : ISpecification < CustomerAccount >  
    {
        
public   override   bool  IsSatisfiedBy(CustomerAccount candidate)
        {       
            
return  candidate.NumberOfRentalsThisMonth  >=   5 ;        
        }
    }
  
  这个规则定义出来后,我们就在业务类中使用这个规则:     
 
代码
        private ISpecification<Customer> specification = null;
  
  当然,我们可以把更多的业务规则组合进来。
  这个例子到这里就完了,这个例子中只是简单的采用了 Specifiction 模式。但是实际的情况往往是没有这个简单的,因为一个业务逻辑往往要组合多个多个业务规则。下面我们就来进一步的看:如果采用链式的结构来完成复杂的业务逻辑。
 
  Composite Pattern (组合模式)
  :这个模式不属于架构模式,而且 GOF 模式的一种,这里列出来主要是为了配合之前的 Specification 模式 的,大家不要在这里纠结这个问题  J
 
  Composite 模式允许把一个集合对象当做单个的对象来使用,而且我们还可以在这个所谓的 单个对象 中不断的嵌套。采用这种模式,可以把对象的层级关系组合成为“树形”的结构!我个人喜欢把它称为“容器模式”。
 
  其实这个模式在我们在平时的 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 ,我们要进行一系列的规则判定:
用户的账号是否处于激活的状态。
用户之前是否还欠费。
用户租赁DVD 的数量是否达到了规定的数量。
代码
public   class  CustomerAccountStillActiveSpecification : ISpecification < CustomerAccount >   
    {
        
public   override   bool  IsSatisfiedBy(CustomerAccount candidate)
        {
            
return  candidate.AccountActive;
        }
    }
  
上面的代码用来判断用户是否处于激活状态
 
代码
     public   class  CustomerAccountHasLateFeesSpecification : ISpecification < CustomerAccount >   
    {
        
public   override   bool  IsSatisfiedBy(CustomerAccount candidate)
        {
            
return  candidate.LateFees  >   0 ;
        }
    }
 
上面的代码就判断用户是否欠费  
添加完了所有的业务规则之后,好戏就开始了。
我们要把这些业务规则组合起来,放在容器中,然后只要调用父容器的一个方法,规则验证就一层层进行下去,就像我们之前举的 ASP.NET Init 事件一样。
 
首先我们来添加一个表示容器的类:
 
代码
   public   abstract   class  CompositeSpecification < T >  : ISpecification < T >
    {
        
public   abstract   bool  IsSatisfiedBy(T candidate);

        
public  ISpecification < T >  And(ISpecification < T >  other)
        {
            
return   new  AndSpecification < T > ( this , other);
        }
      
        
public  ISpecification < T >  Not()
        {
            
return   new  NotSpecification < T > ( this );
        }
    }
  
上面的代码有些不明白的地方,没什么,咱们耐心的往下面走。  
 
代码
public   class  AndSpecification < T >  : CompositeSpecification < T >
    {
        
private  ISpecification < T >  _leftSpecification;
        
private  ISpecification < T >  _rightSpecification;

        
public  AndSpecification(ISpecification < T >  leftSpecification, ISpecification < T >  rightSpecification)
        {
            _leftSpecification 
=  leftSpecification;
            _rightSpecification 
=  rightSpecification;
        }

        
public   override   bool  IsSatisfiedBy(T candidate)
        {
            
return  _leftSpecification.IsSatisfiedBy(candidate)  &&  _rightSpecification.IsSatisfiedBy(candidate);
        }
    }
 
代码
  public   class  NotSpecification < T >  : CompositeSpecification < T >
    {
        
private  ISpecification < T >  _innerSpecification;

        
public  NotSpecification(ISpecification < T >  innerSpecification)
        {
            _innerSpecification 
=  innerSpecification;
        }

        
public   override   bool  IsSatisfiedBy(T candidate)
        {
            
return   ! _innerSpecification.IsSatisfiedBy(candidate);
        }
    }
  
上面基础代码完成了,我们就开始实现我们想要的链式的效果!
我们修改之前的几个规则,和接口的定义,如下:
 
代码
public   class  HasReachedRentalThresholdSpecification :CompositeSpecification < CustomerAccount >
{
        …
}

public   class  CustomerAccountStillActiveSpecification :CompositeSpecification < CustomerAccount >
{
       …
}

public   class  CustomerAccountHasLateFeesSpecification :CompositeSpecification < CustomerAccount >
{
      …
}
  
漫长的过程终于结束了,到了核心的部分,请看业务类现在的定义:
 
public  class Customer
{
          private ISpecification<Customer> hasReachedRentalThreshold;
         private ISpecification<Customer> customerIsActive;
         private ISpecification<Customer> customerHasLateFees;

         public Customer()
        {
          hasReachedRentalThreshold =  new HasReachedMaxSpecification();
            customerIsActive =  new CustomerAvtiveSpecification();
            customerHasLateFees =  new CustomerHasLateFeesSpecification();
        }

         public  decimal TotalRentNumber {  getset; }
         public  bool IsActive {  getset; }
         public  decimal LateFees {  getset; }

         public  bool CanRent()
        {
            ISpecification<Customer>canRent =customerIsActive.And(hasReachedRentalThreshold.Not()).And(customerHasLateFees.Not());
             return canRent.IsSatisfiedBy( this);
        }
}
大家主要看看那个  CanRent 方法
下面我们就来讲讲这个方法。
customerAccountActive 继承自 CompositeSpecification, Add 方法的定义如下:
 
public  ISpecification < T >  And(ISpecification < T >  other)
{
     
return   new  AndSpecification < T > ( this , other);
}
   
  _customerAccountIsActive.And(_hasReachedRentalThreshold.Not()) 的结果就是使得 customerAccountIsActive 内部包含了平行的两条业务规则,结构如下:
 
 
 
  方法返回的结果还是一个实现了 ISpecification 的对象,只不过这个对象(我们称之为“容器 A ”)里面有两个规则了。
  然后这个保量两个业务规则的对象(容器 A )再次调用 Add 方法,如下:
 
  _customerAccountIsActive.And(_hasReachedRentalThreshold.Not()).
And(_customerAccountHasLateFees.Not());
 
  此时相当于把之前那个容器 A 作为一个单独对象,再次调用 Add 方法,于是这个三个规则组合成为一个大的规则的容器:如下。
 
 
今天就到这里,东西不多,大家多琢磨一下!



















本文转自yanyangtian51CTO博客,原文链接: http://blog.51cto.com/yanyangtian/423279  ,如需转载请自行联系原作者

相关文章
|
4天前
|
Cloud Native 安全 API
云原生架构下的微服务治理策略与实践####
—透过云原生的棱镜,探索微服务架构下的挑战与应对之道 本文旨在探讨云原生环境下,微服务架构所面临的关键挑战及有效的治理策略。随着云计算技术的深入发展,越来越多的企业选择采用云原生架构来构建和部署其应用程序,以期获得更高的灵活性、可扩展性和效率。然而,微服务架构的复杂性也带来了服务发现、负载均衡、故障恢复等一系列治理难题。本文将深入分析这些问题,并提出一套基于云原生技术栈的微服务治理框架,包括服务网格的应用、API网关的集成、以及动态配置管理等关键方面,旨在为企业实现高效、稳定的微服务架构提供参考路径。 ####
24 5
|
7天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
5天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型浪潮中,企业纷纷拥抱云计算,而云原生架构作为其核心技术支撑,正引领着一场深刻的技术变革。本文聚焦于云原生环境下微服务架构的治理策略与实践,探讨如何通过精细化的服务管理、动态的流量调度、高效的故障恢复机制以及持续的监控优化,构建弹性、可靠且易于维护的分布式系统。我们将深入剖析微服务治理的核心要素,结合具体案例,揭示其在提升系统稳定性、扩展性和敏捷性方面的关键作用,为读者提供一套切实可行的云原生微服务治理指南。 ####
|
5天前
|
消息中间件 缓存 Cloud Native
云原生架构下的性能优化实践与挑战####
随着企业数字化转型的加速,云原生架构以其高度解耦、弹性伸缩和快速迭代的特性,成为现代软件开发的首选模式。本文深入探讨了云原生环境下性能优化的关键策略与面临的主要挑战,通过案例分析,揭示了如何有效利用容器化、微服务、动态调度等技术手段提升应用性能,同时指出了在复杂云环境中确保系统稳定性和高效性的难题,为开发者和架构师提供了实战指南。 ####
18 3
|
5天前
|
运维 Kubernetes Cloud Native
深入理解云原生架构:从理论到实践
【10月更文挑战第38天】本文将引导读者深入探索云原生技术的核心概念,以及如何将这些概念应用于实际的软件开发和运维中。我们将从云原生的基本定义出发,逐步展开其背后的设计哲学、关键技术组件,并以一个具体的代码示例来演示云原生应用的构建过程。无论你是云原生技术的初学者,还是希望深化理解的开发者,这篇文章都将为你提供有价值的见解和实操指南。
|
5天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
19 3
|
5天前
|
运维 Kubernetes Cloud Native
云原生技术在现代应用架构中的实践与挑战####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在实际项目中的应用案例,分析了企业在向云原生转型过程中面临的主要挑战及应对策略。不同于传统摘要的概述性质,本摘要强调通过具体实例揭示云原生技术如何促进应用的灵活性、可扩展性和高效运维,同时指出实践中需注意的技术债务、安全合规等问题,为读者提供一幅云原生技术实践的全景视图。 ####
|
6天前
|
缓存 负载均衡 JavaScript
探索微服务架构下的API网关模式
【10月更文挑战第37天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。它不仅是客户端请求的集散地,更是后端微服务的守门人。本文将深入探讨API网关的设计哲学、核心功能以及它在微服务生态中扮演的角色,同时通过实际代码示例,揭示如何实现一个高效、可靠的API网关。
|
4天前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
5天前
|
Dubbo Java 应用服务中间件
服务架构的演进:从单体到微服务的探索之旅
随着企业业务的不断拓展和复杂度的提升,对软件系统架构的要求也日益严苛。传统的架构模式在应对现代业务场景时逐渐暴露出诸多局限性,于是服务架构开启了持续演变之路。从单体架构的简易便捷,到分布式架构的模块化解耦,再到微服务架构的精细化管理,企业对技术的选择变得至关重要,尤其是 Spring Cloud 和 Dubbo 等微服务技术的对比和应用,直接影响着项目的成败。 本篇文章会从服务架构的演进开始分析,探索从单体项目到微服务项目的演变过程。然后也会对目前常见的微服务技术进行对比,找到目前市面上所常用的技术给大家进行讲解。
16 1
服务架构的演进:从单体到微服务的探索之旅

热门文章

最新文章