最常见的体系结构模式是分层体系结构模式,也称为n层体系结构模式。这种模式是大多数Java EE应用程序的事实标准,因此被大多数架构师,设计人员和开发人员广为人知。分层架构模式与大多数公司中的传统IT通信和组织结构紧密匹配,使其成为大多数业务应用程序开发工作的自然选择。
模式说明
分层体系结构模式中的组件被组织成水平层,每个层在应用程序内执行特定角色(例如,表示逻辑或业务逻辑)。尽管分层体系结构模式未指定模式中必须存在的层的数量和类型,但大多数分层体系结构由四个标准层组成:表示层,业务层,持久层和数据库。在某些情况下,业务层和持久层将组合到单个业务层中,尤其是当持久性逻辑(例如,SQL或HSQL)嵌入到业务层组件中时。因此,较小的应用程序可能只有三层,而较大和较复杂的业务应用程序可能包含五层或更多层。
分层体系结构模式的每一层在应用程序中都具有特定的角色和职责。例如,表示层将负责处理所有用户界面和浏览器通信逻辑,而业务层将负责执行与请求相关联的特定业务规则。体系结构中的每个层都围绕着需要完成的工作的抽象来满足特定的业务请求。例如,表示层并不需要知道或者担心关于如何获取客户数据; 它只需要在屏幕上以特定格式显示该信息。同样,业务层不需要关心如何格式化客户数据以在屏幕上显示甚至客户数据来自何处; 它只需要从持久层获取数据,对数据执行业务逻辑(例如,计算值或聚合数据),并将该信息传递到表示层。
分层架构模式的一个强大功能是组件之间的关注点分离。特定层中的组件仅处理与该层相关的逻辑。例如,表示层中的组件仅处理表示逻辑,而驻留在业务层中的组件仅处理业务逻辑。这种类型的组件分类使您可以轻松地在架构中构建有效的角色和责任模型,并且由于定义良好的组件接口和有限的组件范围,还可以使用此体系结构模式轻松开发,测试,管理和维护应用程序。
关键概念
请注意,如下图,架构中的每个层都标记为已 关闭。这是分层架构模式中非常重要的概念。封闭层意味着当请求从一个层移动到另一个层时,它必须通过它下面的层才能到达该层下面的下一层。例如,源自表示层的请求必须首先通过业务层,然后在最终命中数据库层之前到达持久层。 其本质就是为了 解耦合。
那么为什么不允许表示层直接访问持久层或数据库层呢?毕竟,从表示层直接访问数据库比通过一堆不必要的层只是为了检索或保存数据库信息要快得多。这个问题的答案在于一个被称为隔离层的关键概念 。
隔离层概念意味着在体系结构的一个层中所做的更改通常不会影响或影响其他层中的组件:更改与该层中的组件隔离,并且可能与另一个关联层(例如包含持久层) SQL)。如果允许表示层直接访问持久层,那么在持久层中对SQL所做的更改将影响业务层和表示层,从而产生一个紧密耦合的应用程序,在组件之间具有许多相互依赖性。这种类型的架构变得非常困难且变得昂贵。
隔离层的概念还意味着每个层独立于其他层,因此很少或根本不了解架构中其他层的内部工作。要了解此概念的强大功能和重要性,请考虑将表示框架从JSP(Java Server Pages)转换为JSF(Java Server Faces)的大量重构工作。假设表示层和业务层之间使用的合同(例如,模型)保持不变,业务层不受重构的影响,并且完全独立于表示层使用的用户界面框架的类型。
虽然封闭层有助于隔离层,因此有助于隔离架构内的变化,但有时候某些层是开放的是有意义的。例如,假设您要将共享服务层添加到包含业务层内组件访问的公共服务组件的体系结构(例如,数据和字符串实用程序类或审计和日志记录类)。在这种情况下,创建服务层通常是个好主意,因为在架构上它限制了对业务层(而不是表示层)的共享服务的访问。如果没有单独的层,则在架构上没有任何内容限制表示层访问这些公共服务,从而难以管理此访问限制。
在此示例中,新服务层可能位于 业务层下方,以指示无法从表示层访问此服务层中的组件。然而,这提出了一个问题,即业务层现在需要通过服务层才能到达持久层,这根本没有意义。这是分层体系结构的一个古老问题,可以通过在体系结构中创建开放层来解决。
如下图所示,在这种情况下,服务层被标记为打开,这意味着请求被允许绕过这个开放层,直接进入它下面的层。在下面的示例中,由于服务层是打开的,现在允许业务层绕过它并直接转到持久层,这非常有意义。
利用开放层和封闭层的概念有助于定义架构层和请求流之间的关系,并为设计人员和开发人员提供必要的信息,以了解架构中的各种层访问限制。未能记录或正确地传达体系结构中的哪些层是开放和关闭的(以及为什么)通常会导致紧密耦合和脆弱的体系结构,这些体系结构非常难以测试,维护和部署。
模式示例
为了说明分层体系结构的工作原理,请考虑业务用户请求检索特定个人的客户信息,如下图所示。黑色箭头表示请求流向数据库以检索客户数据,红色箭头表示响应流回屏幕以显示数据。在此示例中,客户信息包括客户数据和订单数据(客户下订单)。
的顾客屏幕是负责接受该请求,并显示所述客户信息。它不知道数据的位置,检索方式,或者必须有多少数据库表才能获取数据。一旦客户屏幕收到获取特定个人的客户信息的请求,它就会将该请求转发给客户委托模块。该模块负责了解业务层中的哪些模块可以处理该请求,以及如何访问该模块以及它需要哪些数据(合同)。业务层中的客户对象负责聚合业务请求所需的所有信息(在这种情况下,以获取客户信息)。这个模块呼唤了 客户dao (数据访问对象)模块在持久层中获取客户数据,并且还为订单dao模块获取订单信息。这些模块依次执行SQL语句以检索相应的数据并将其传递回业务层中的客户对象。一旦客户对象接收到数据,它就会聚合数据并将该信息传递回客户代表,然后客户代表将该数据传递给客户屏幕以呈现给用户。
从技术角度来看,这些模块可以通过几十种方式实现。例如,在Java平台中,客户屏幕可以是(JSF)Java Server Faces屏幕,其与客户委托作为托管bean组件耦合。业务层中的customer对象可以是本地Spring bean或远程EJB3 bean。上一个示例中说明的数据访问对象可以实现为简单的POJO(普通旧Java对象),MyBatis XML Mapper文件,甚至是封装原始JDBC调用或Hibernate查询的对象。从Microsoft平台的角度来看,客户屏幕可以是ASP(活动服务器页面)模块,使用.NET框架访问业务层中的C#模块,客户和订单数据访问模块实现为ADO(ActiveX数据对象)。
注意事项
分层体系结构模式是一种可靠的通用模式,使其成为大多数应用程序的良好起点,特别是当您不确定哪种体系结构模式最适合您的应用程序时。但是,在选择此模式时,从架构的角度来看,有几件事需要考虑。
首先要注意的是所谓的建筑物下沉式反模式。此反模式描述了请求流经架构的多个层的情况,即在每个层内执行很少或没有逻辑的简单直通处理。例如,假设表示层响应来自用户的检索客户数据的请求。表示层将请求传递给业务层,业务层只是将请求传递给持久层,持久层然后对数据库层进行简单的SQL调用以检索客户数据。然后,数据一直传递回堆栈,无需额外的处理或逻辑来聚合,计算或转换数据。
每个分层架构至少会有一些属于架构下沉反模式的场景。然而,关键是分析属于此类别的请求的百分比。80-20规则通常是一个很好的做法,以确定您是否正在体验建筑物下沉反模式。通常,大约20%的请求是简单的传递处理,80%的请求具有与请求相关的一些业务逻辑。但是,如果您发现此比率相反且大多数请求都是简单的传递处理,您可能需要考虑使某些架构层处于打开状态,请记住,控制更改将更加困难缺乏层隔离。
分层体系结构模式的另一个考虑因素是,即使将表示层和业务层拆分为单独的可部署单元,它也倾向于使用单片应用程序。虽然这可能不是某些应用程序的问题,但它确实在部署,一般健壮性和可靠性,性能和可伸缩性方面存在一些潜在问题。
模式分析
整体敏捷
评级:低
分析:整体敏捷性是指能够快速响应不断变化的环境。虽然可以通过此模式的隔离层来隔离更改,但是由于大多数实现的单一性质以及通常与此相关的组件的紧密耦合,因此在此体系结构模式中进行更改仍然是麻烦且耗时的。
易于部署
评级:低
分析:根据您实现此模式的方式,部署可能会成为一个问题,尤其是对于大型应用程序。对组件的一个小改动可能需要重新部署整个应用程序(或应用程序的大部分),从而导致需要在非工作时间或周末进行计划,安排和执行的部署。因此,这种模式不容易适应连续交付管道,进一步降低了部署的总体评级。
可测性
评级:高
分析:由于组件属于体系结构中的特定层,因此可以模拟或存根其他层,从而使此模式相对容易测试。开发人员可以模拟演示组件或屏幕以隔离业务组件中的测试,以及模拟业务层以测试某些屏幕功能。性能评级:低分析:虽然某些分层体系结构可以很好地运行,但由于必须经过多层体系结构来满足业务请求的效率低下,因此该模式不适合高性能应用程序。
可扩展性
评级:低分
析:由于此模式的紧密耦合和单一实现的趋势,使用此体系结构模式构建的应用程序通常难以扩展。您可以通过将层拆分为单独的物理部署或将整个应用程序复制到多个节点来扩展分层体系结构,但总体而言,粒度太宽,使得扩展成本很高。
易于开发
评级:高
分析:易于开发得分相对较高,主要是因为这种模式众所周知,并且实施起来并不复杂。由于大多数公司通过按层(表示,业务,数据库)分离技能集来开发应用程序,因此该模式成为大多数业务应用程序开发的自然选择。概述了公司的沟通和组织结构与其开发软件的方式之间的联系,即所谓的 康威定律。你可以谷歌“康威定律”更多信息。
参考地址:https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html