英语原文共 22 页,剩余内容已隐藏,支付完成后下载完整资料
反转控制层
1.引言
在复杂的软件系统中实现并重用的重要且广泛建立的架构设计实践是在专用软件组件中捕获循环行为(例如,指令调用方面的活动流程),即通过与这些组件集成并从客户端组件配置它们,可以在各种应用程序中应用组件的预定义行为。在过去,这种建筑设计实践已经以多种方式进行了标注。例如,Johnson&Foote在基于抽象类的设计方面讨论了控制的反转。使用术语反转意味着应用框架,框架整合应用程序和它们之间的典型控制方向(即控制框架的应用程序)之间的区别。控制的反转意味着在这种情况下,这种控制方向通过某些方式反转,允许框架至少部分地和以明确的方式控制应用程序描述的行为。从结构的角度来看,这反映在管理呼叫和使用依赖性的责任倒置中,也称为依赖性反转。
近年来,诸如PicoContainer和Spring等轻型组件容器在设计实践中提出了控制反转的新观点,而不是基于抽象类或接口。他们在这些容器中使用称为依赖注入的组件布线技术,实现了控制的反转。依赖注入的基本思想,是提供一种特殊的对象,用于通过不同风格的参数化委托来连接组件。
控制反演历史的简短和非穷尽概述主要限于OO语言,OO框架和轻量级容器的上下文,表明该设计实践重新出现在不同系列的软件系统中,适用于各种技术的软件解决方案域:GUI应用程序框架,远程框架,事件驱动的I / O,OO编程语言设计,面向组件的编程等。同时,软件工程师可以实现各种各样的设计和实现技术来实现反转控制。
控制的反转有可能影响软件系统的架构质量,必须在相关架构设计决策的背景下考虑。然而,目前关于建筑模式的工作并没有记录这种建筑设计实践。捕获它作为一种建筑模式描述使我们能够评估其相互作用以及相关的建筑模式,最显着的是“层”,“显示界面”和“从上方的参数”模式。
2.情景模式
构建软件架构的基本方法是引入分层。 LAYERS建筑模式描述了垂直和水平责任相关系统的分解。驻留在相同粒度级别的组件被分组成LAYERS,并且每个层提供到下一个更高层的接口。只有从一个层n到其下一个较低级别层n-1的调用是可能的,并且通常忽略层被禁止。
层之间的接口通常被实现为EXPLICIT INTERFACES。 EXPLICIT INTERFACE模式处理如何避免调用方对被调用组件的实现细节的依赖。 EXPLICIT INTERFACE模式建议人们在接口(规范)和被调用组件的实现之间进行分离。
LAYERS模式涉及系统分层分解为功能响应的层次以及使用依赖关系的特定结构。这些依赖关系采取严格的自上而下的方向,以纯粹的形式,通过禁止中间层的旁路来保护它们。每个单个层将组件及其连接器组合在一个可比较的粒度级别。显式接口连接层中下层提供了一个EXPLICIT INTERFACE,负责通过实现接口的组件来实现该所需。翻转侧是较高层需要显示界面规定的行为。这种依赖结构反映了组件之间的预期控制流程。由EXPLICIT INTERFACES广告和屏蔽的指令,是从较高级别的LAYERS的组件中进行的。
3.动作示例
在本块内容中,我们使用企业资源规划(ERP)领域的具体示例来说明“INVERSION-OF-CONTROL LAYER”模式的问题。我们可以考虑计划创建一个面向对象的小型应用程序框架,以便使用Java。订单管理本身包括许多子任务,如放置,删除和跟踪订单。根据开发套件及其应用框架,开始为客户A和客户B创建三个应用程序:客户A委托两个应用程序,一个用于将订单管理与网上商店环境集成,另一个用于链接将其呼叫中心连接到订单管理并且客户B还经营没有呼叫中心网络商店。
从业务流程的角度来看,三个目标应用程序需要相当类似的传入订单处理步骤,然而,处理步骤不完全相同。订单处理涉及到几个动作的流程。在第一步中,总订单价格是根据有序项目和单个物品价格计算的。然后,根据计算的订单总额来验证客户特定的支出限额。如果审查中的订单请求违反了此支出限额,那么它会发出违规信号,触发回滚并清除订单请求。如果支出限制约束得到满足,那么应用程序必须检查是否向客户授予非累积数量折扣。如果审查的订单请求达到数量阈值,那么降价必须生效。完成这两个准备任务后,订单请求实际上被放置并转换成存储顺序。根据此订单和计算的订单价格,生成发票作为最终动作。
4、反向控制层
人们所需架构一定是严格分层的。 LAYERS需要并自上而下地提供EXPLICIT INTERFACES,从上到下,从上到下。随着时间的推移,架构将部署在不同的需求设置或产品配置中。在这种情况下,计划重新构建复杂和复合行为的更高版本的重用。例如,它可以在单个或甚至多个目标域中识别业务流程描述中的重复相似性。然而,现在组件应为任意客户端提供共享行为(例如,过程描述)的实现,希望确保客户端组件可以按照精确的协议来在这些重用的行为单元中细化所选和预定义的步骤。理想情况下,在执行共享行为时管理输入和输出需求的需求应该是最小化的,并由EXPLICIT INTERFACE引导。
但是,如果两层(例如,应用程序和框架层)通过严格的单向,自上而下的使用关系(例如自上而下的指令调用)进行链接,则无法将潜在的共享和可重用同时保留原始的自上而下的单向调用依赖结构。这是因为重复使用行为描述并且同时保持通过客户端组件适应性的某些步骤需要以某种方式或另一种方式从下层呼叫到更高的层次。
如何在LAYERS架构中为多个客户端组件提供重用行为定义,同时允许每个客户端组件在预定义点改进和偏离重用的控制和数据流呢?
当以严格和未精确的方式使用LAYERS时,将自己限制在特定类型的重用是不可避免的。 LAYERS结构希望我们将复合行为的实现放置在所有层的提供复合行为的各个部分之上,并且这是以维护分层架构中自上而下的调用依赖性为前提的。
因此,人们必须询问自己是否应用严格的LAYERS结构导致的两层(即应用程序和框架层)之间的自上而下依赖关系是否能够最大限度地重用共享进程资源(即控制和数据流,操作和对象)潜在的客户端组件之间。换句话说,在哪个程度上是可能共享的过程资产,放置在较高(例如框架)层上并可从其获得?较低级别层次的行为实现应该是从更高层次的角度来看是可修改的,可移植的和可重复使用的。
很明显,像LAYERS模式中提出的严格分层分解并不总是足够的。层之间的相互作用是单向的,并且被限制为由EXPLICIT IN-TERFACES提供的协议。在其最纯粹的形式中,通过EXPLICIT INTERFACE暴露的行为被认为是无状态的,因此是没有副作用的。也因此,如果在较高层的客户端组件需要多个配置,则纯分层结构可能会很麻烦。
解决方案必须在可用于分层的不同设计策略下实现,例如基于类的编程语言。一方面,层次化可以通过沿着类层次结构的方法传播来实现,有时也称为通过继承分层。另一方面,可以通过建立和管理方法体内的对象的调用引用来实现分层。这种变体通常被称为按层次分组。基于继承的分层属于白盒重用类别,这是各种细化可能性的范围以及对类层次结构的每个级别内部的不必要依赖的原因。呼叫组合表示黑盒重用,因为依赖关系限于所引用对象的签名接口。同时,内部部件对于调用组件仍然是完全不透明的,从而阻止它们实际上损害被重用的行为。
在许多架构中,给出了一般控制流程和主要组件,但是不同的应用程序包含不同的用户定义的细化(例如,类),其应该扩展基础组件,在架构的较低层中定义,并具有自定义行为。通过使用自上而下的参数化(例如,连续地将配置值通过每个层)来配置数据来进行配置是相当麻烦的,关于如何将配置值转换为可重复使用的复合行为的可观察的变化的解决方案仍然与应用程序开发人员保持密封。此外,参数传递意味着我们需要在较低级别的层中预见哪些配置选项是可能的。普通形式参数的容许度和灵活性太过于约束,单独通过简单形式的PARAMETRIZE(例如扩展操作参数列表)从较高层配置较低。
5.动态实例解决
到目前为止,我们的订单子框架的激励例子已经假设必须保持遵循LAYERS模式的严格自上而下的调用依赖结构。诸如org.B.WebOrderRequest或org.A.PgSqlOrderRequest之类的应用程序层组件保持对框架层组件的单向引用,即分别与erp.ordering.OracleOrderRequest的依赖关系和与erp.ordering.OrderRequest的泛化关系。获得某些流程资产的实施重用(例如,诸如calculatePrice()之类的常见流程步骤,以及组织诸如getSpendingLimit())之类的存储特定行为。
然而,有进一步重用的潜力。也就是说,可以实现所有客户端应用程序之间的整个流程定义的共享,即由process()方法描述的控制和数据流。然而,改变这种行为定义的所有权会影响LAYERS结构。这种重构将架构配置修改为INVERSION-OF-CONTROL LAYER架构。
这说明了在这种重构之前,共享和非共享进程资源在应用程序和框架层之间的分布。对这些数据项的数据项和操作的共享定义显示为实心圆,每个客户端应用的特定数据和操作都标记为空圆圈。定义整体排序过程的行为声明仍然由每个客户端应用程序专有,而有可能重用。因此,一些行为声明被所有客户端应用程序冗余地包含。
现在,考虑对框架层进行控制和数据流定义的逐步重构,采用不同但又互补的设计实践:使用TEMPLATE METHOD和钩子方法,组合和授权的摘要类设计,以及依赖关系的形式。这三种不同但架构相关的重构方法将在框架和应用层之间引入反向或自下而上的接口要求。
6、实例和已知的用途
在面向对象(OO)应用程序框架中使用INVERSION-OF-CONTROL LAYER模式的不同变体,将OO应用程序框架与基于类库的复用区别开来。类图书馆面临重复开发工作的风险以及缺乏复用的可能性。重复的复杂性和复杂性的复杂性来自组合以不同方式提供的行为,即使在同一开发项目中也可以获得与可比较和相关设计问题不同的解决方案。最重要的是,类库不允许捕获控制流设计以供重用,这样可以适用于不同的设计和实现问题。使用类库的应用程序开发人员仍然负责为库提供的重用实体以及其他方面布置具体的控制流程(例如,对象排序和消息路径)。根据开发人员团队的熟练程度,以应用程序特定的方式设计和实施控制流程可以阻止其重复使用和容易出错的风险。
从架构视角来看,OO应用程序框架展现了由LAYERS所描述的结构,应用程序将框架组件集成在最顶层的LAYER(应用程序或集成器层)中,该层可以知道至少一个但通常是几个控制层(即框架层)作为其直接后代。在积分器层发出的指令呼叫导致触发和初始化对位于INVERSION-OF-CONTROL LAYER的特定组件的呼叫。这反过来又导致控制组件反转中的框架级控制流程被执行。也就是说,执行在INVERSION-OF-CONTROL LAYER和更高级别层中的组件的协作。
用于实现以类为中心和类专业语言实现应用框架的强制控制层的重要设计技术是AB-STRACT CLASSES的变体,虽然略有扩展的内涵,有时也是提到基础类或模板类。这些作品主要假设没有语言机制,构造或成语可用于帮助实施INVERSION-OF-CONTROL LAYER模式。许多编程语言为此提供了明确的语言结构,例如Java和C#中的接口构造,这些结构将在下面讨论。这种设计实践的核心是使用超类来指定签名接口,并且实现对象协作,控制和数据流的可重用设计。
7.相关工作
已经从不同的,经常互补的观点来讨论和评估反转控制。反向的控制方向被称为好莱坞法或以后的好莱坞原则 :“不要打电话给我们,我们会打电话给你。”Sweet向读者介绍了施乐开发环境(XDE)的设计,这是一个Mesa语言和运行时平台的集成开发环境。作为一个重要的基础架构元素,XDE允许扩展开发人员添加自己的开发工具,这些附加组件能够交换通知。该工具间通知方案是通过允许工具开发人员使用整个XDE窗口和执行系统Tajo来注册回调过程来实现的(例如,睡眠和唤醒过程)。所以说:“不要打电话给我们,我们会给你打电话”。好莱坞法律也与许多GoF设计模式有关,特别是GoF模板方法模式及其概括。
超越OO编程,控制反转作为行为重用的一个平均值可以追溯到实践,特别是过程调用抽象的某些用途。例如,通过函数指针的回调在许多C库中用于在库代码中运行应用程序代码。这些做法影响了早期的OO语言设计。在OO编程的起源,Simula-67介绍了内部方法组合的策略以及类前缀的思想。简单地来说,超类拥有的方法被允许调用它们的阴影子类方法。这种方法组合的风格由OO编程的Beta传统(即Beta的内部机制[Madsen等人,1993])继续,以实现特定的专门化方案:超类方法(即Beta中的一般动作)任务(即部分动作),通过超类方法排序成序列。内部机制允许通过沿着继承路径细化部分动作来逐步专门化此一般动作。
在模式社区中,这不是模式形式反转控制实践的第一个讨论。例如,在POSA1在不同层之间的特定调用依赖关系被讨论为基于回调的自下而上的通信。然而,这里的重点是保留上下层之间的自上而下的单向去耦,同时仍然反转一些控制。对POSA1的这种反转控制的架构需求并不是中心的。除此之外,参考回调的使用只会将自下而上通信的概念减少到这种隐式调用形式。以前已经介绍了许多类似于其他模式作品的例子。相比之下,本文提出的工作侧重于反演层次的建筑设计决策,将控制层的反演设置为相关模式的背景,并讨论了应用的主要力量和后果模式。本文中已经给出了许多实例和已知的用途来说明在实践中使用该模式。控制倒置在管理分层系统中的变异点时,也会产生一些互补的架构设计实践来反转责任。这些模式主要涉及通过参数化的组件配置,捕获了重复的架构设计挑战,这些挑战要求从顶级层以有纪律的方式参与分层系统。这些挑战反映了几个不同领域的经验,即软件测试,插件和容器基础设施,参数传递策略以及编程语言设计(例如,口译员)。<!--
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[137177],资料为PDF文档或Word文档,PDF文档可免费转换为Word
课题毕业论文、外文翻译、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。