读书人

Posa的114类设计模式_组4、5、6

发布时间: 2012-10-25 10:58:57 作者: rapoo

Posa的114种设计模式_组4、5、6

第四章 接口划分

组件接口设计的要求:1)组件职责和约定规范 2)质量属性 3)可表达性和简洁性 4)松耦合和稳定性。

Explicit Interface

软件架构的所有工作主要是围绕如何有效而恰当地表现组件接口。

组件代表一个自我完备的担忧,包括其功能、部署和使用协议。客户端使用这些组件来构建自己的功能,然而,直接访问组件的全部实现,会使得客户端依赖于组件的内部细节,最终会增加应用的内部软件耦合。解决方法:将组件的声明接口与其实现分开,将组件的接口导出给客户端,但是对客户端保存期实现的私有性和位置无关性。

结构:

Posa的114类设计模式_组4、5、6

Explicit Interface在组件接口和具体实现之间进行了严格的划分,是组件的使用问题与具体实现及位置细节分离开。

接口设计:

Posa的114类设计模式_组4、5、6

Extension Interface

在实现Explicit Interface 时,我们希望接口升级的时候,确保客户端的稳定性和类型安全性。

只有在组件提供稳定而内聚的接口时,客户端才能有效的使用它。然而,功能的改变或者扩展往往会影响到组件的接口,这将对客户端代码产生破坏,计算新功能并为被使用。解决方法:让客户端只通过特化的Extension访问组件,并且为组件提供的每个角色引入一个这样的接口,当组件需要增加新功能或者更新已有的签名时,都有引入新的Extension Interface(类似于Com? 接口只增不减?)。

结构:

Posa的114类设计模式_组4、5、6

实现方式:首先确定它在全部预想的使用场景中可能扮演的角色,将每个角色封装到单独的Extension Interface,并只允许客户端通过访问这些Interface来完成各自的工作。避免修改已有的Extension Interface,为组件扩展新功能或者更新已有服务的签名时,创建新的Extension Interface。

组成:每一个角色专属的Extension Interface都可以是Explicit Interface。

接口类型:

Posa的114类设计模式_组4、5、6

Introspective Interface

在实现Reflection架构或者Extension的根接口的时候,有时必须允许客户端访问它们所使用的组件的信息,即元数据。

客户端需要正确地使用组件可能需要访问组件的某些信息,例如其类型、标示、所支持接口或当期状态。然而允许客户端直接访问这种技术细节可能会破坏组件的封装性,并降低依赖的稳定性。解决方法:为组件引入专门的Introspective Interface以允许客户端访问器内部机制和结构的信息,将反射接口和组件的操作接口分离开。

结构:

IntrosPosa的114类设计模式_组4、5、6pective Interface提供对组件的受控访问而不破坏器封装性,将组件的使用和获取器信息分开,不依赖于组件的特定接口、内部设计和实现(一般作物可选接口实现,在需要访问组件元数据时使用)。

Dynamic Invocation Interface

允许访问组件的功能而不必知道或使用期静态类型接口

组件的Explicit Interface声明提供了一系列的协议,但是有时候我们需要组件支持而外的方法调用,当客户端必须调用组件失效不知道的额外功能时,这种开放性就非常必要了。解决方法:为那些运行客户端动态调用的组件引用一个Dynamic Invocation Interface与组件的操作接口隔离开。

结构

Posa的114类设计模式_组4、5、6

优点:为客户端调用组件提供了另一种选项,这种方式基于动态协议,是开放的非入侵的,增强了客户端应用的灵活性。

缺点:延迟绑定不能及时检查出现的错误协议或者错误实现,对动态调用的的检测比静态调用检测有更多的限制,而且性能开销较大。

方法调用

Posa的114类设计模式_组4、5、6

Proxy

我们经常避免直接访问组件实现的服务。

软件系统中包含的组件是相互协作的,客户端组件访问并使用其他组件提供的服务。通常,直接访问组件的服务是不现实的,甚至是不可能的,例如我们必须首先检查客户端的访问权限,或者是因为组件的实现位于远程服务器中。解决方法:将所有组件的内务相关功能封装成一个单独的组件替代者-Proxy 并让客户端通过Proxy通信,而不是直接访问组件本身。(代理)

结构

Posa的114类设计模式_组4、5、6

接口类型

Posa的114类设计模式_组4、5、6

Business Delegate

组件的访问来源可能是另外一个地址空间。

因为网络的性能和可靠性等原因,远程访问组件和访问本地组件由很大的不同。理想情况下,客户端不需要关心其使用的是本地还是远程的组件。解决方法:为每个远程组件引入一个Business Delegate,它的创建、使用和销毁都跟本地组件易于,而且其接口与所代表的组件完全一致。由Business Delegate 完成所有的网络任务,这堆使用组件的客户端是完全透明的。

结构:

Posa的114类设计模式_组4、5、6

Facade

有时我们需要一个组件群,它们共同为客户端提供服务。

复杂的服务通常由一个组件群提供的,其中每个组件都为客户端提供一个自我完备的服务。如果客户端想调用复杂的服务,它必须显示的维护与其中每一个组件之间的关系,然而,这样将使它依赖于组件群的内部结构。解决方法:为组件指定单一的访问点——Facade,在通常的使用场景中将客户端的请求中转给合适的组件,同时也允许特定的更复杂的情况下绕过该访问点。

结构:

Posa的114类设计模式_组4、5、6

除转发请求外,Fa?ade接口在其公开接口和被保护的组件接口间完成所有必需的适配工作,Fa?ade还可以将不同的组件特性聚合成为新的、“更高级”的服务,但是客户端不上必须通过Facade来调用组件,客户端仍然可以直接访问特定组件。

接口类型:

Posa的114类设计模式_组4、5、6

Combined Method

我们经常需要按照相同的顺序来调用某个组件的多个方法。

客户端经常必须按照同样的顺序调用组件的多个方法以执行特定任务,然而从客户端来看,每次都显示地调用它想执行的这些组件方法即繁琐又容易出错。解决方法:将组件中那些必须或者通常一起执行的方法组合成一个方法。

结构:

Posa的114类设计模式_组4、5、6

优点:增强了组件或对象接口的表达能力和内聚性;应用的健壮性也得到了增强,分布式开销只发生一次,非确定性导致的并发性故障被消除,错误处理和恢复策略都被封装,形成更加类似于事务风格的设计。

Iterator

我们经常需要顺序访问聚合的元素而不暴露其内部结构。

客户端经常需要遍历封装在聚合中的元素,但是并不希望与依赖与聚合的内部结构,同时聚合也不希望将内部结构暴露给客户端。解决方法:客户端首先从聚合中获取Iterator,然后客户端使用改Iterator按照一定顺序访问这些元素。

结构

Posa的114类设计模式_组4、5、6

Enumeration Methond

我们可能希望对聚合中的每个元素逐个调用其某个行为。

某些类型的聚合,例如图或树,其表现不适合使用基于Iterator的方式进行辩论,类似的使用Iterator来访问线程间共享的聚合中的元素时,反复的锁操作会引入不必要的开销,对远程聚合访问操作引入的开销更大,虽然如此,我们还是需要高效的访问聚合元素以执行相应的操作。解决方法:将迭代放在聚合内部并封装成一个Enumeration Method以服装完成辩论,将循环的任务——要在聚合的每个元素上执行的动作——作为参数传递给Enumeration Method,再应用到每个元素上。

与Iterator区别:Enumeration Method 执行完整的遍历。

优点:设计更加完整明确,封装性更好且自我完备。

结构:

Posa的114类设计模式_组4、5、6

Batch Method

我们可能希望在聚合上执行大批访问。

有时候客户端希望在聚合上执行大批访问,例如从集合中获取某种特性的所有元素,如果访问聚合开销很大,比如它是远程的或者并发性的,那么单独访问每个元素会引入相当大的性能损失和并发开销。解决方法:设计单独的Batch Method在聚合上重复执行操作。该方法的声明接收每次执行操作所需的全部参数,例如苏州或者集合,结果的返回也采用类似的方式。

结构:

Posa的114类设计模式_组4、5、6

将重复操作合并到数据结构中,而不是在客户端进行循环。

接口类型:

Posa的114类设计模式_组4、5、6

第五章 组件划分

Encapsulate Implementation

根据组件的结构对组件进行实现时非常重要的一件事。

组件通过自己的接口对外提供服务,但是接口只是一个承诺,组件必须通过实现来履行这个承诺。因此,预设、约束等各方面的考虑虽然不能通过接口对外暴露,单正是这些因素制约着组件的实现。组件的实现必须考虑组件的接口定义的契约,各种其他的约束与需求。解决方法:确保将所有组件的实现细节隐藏在其接口的后面,使得用户不会接触到你所选择的具体实现,因为这些选择可能在应用的生命周期内发生变化,或者他们是依赖于组件的特定部署方式的。

结构:

Posa的114类设计模式_组4、5、6

客户端的实现必须严格的依赖与正式公开的接口,组件的实现也必须仰遵守由接口定义的边界。在以上条件下Encapsulated Implementation可以自由的升级,不影响客户端的稳定性。

Encapsulated Implementation的应用:

Posa的114类设计模式_组4、5、6

Whole part

在对Encapsulate Implementation进行划分时,经常需要或者可以将组件对象分解为几个小一点的块。

有些组件对象提供的功能非常多,这时候将这些功能捆绑在一起往往是不切实际的,我们最好将其分开,让每一部实现一部分职责,但是客户端并不想与这么多小块打交道。解决方法:将组件对象看作一个整体,将其划分为多个独立的Part,使用Whole进行封装,为Whole定义一个接口。这个接口是客户端访问组件的唯一接口。

结构:

Posa的114类设计模式_组4、5、6

注:part往往本身就是独立的组件,甚至是本身具有Whole-Part结构

两个主要的问题:1)对Part的共享 2)对Part的生命周期管理。

Composite

有时候 我们需要按照统一的方式对待原子元素或者Whole-Part结构中的组合元素。

有时候整个层次结构有支持相同的接口的对象以递归的方式构成。然而客户端通常不关心具体的组织形式及其结构中的递归特性。它们只希望将整个层次结构作为一个增添来使用和交互。在整体的内部我们必须保持层级结构,而且在层级结构内部对象重新组合或者层级结构进行扩展时,整个层级结构应该保持稳定。

解决方法:声明一个组件结构,通过这个接口来确定层级结构的整体中所有对象的共同职责,并通过对这个接口进行子类化来实现整体内部的具体对象,已经由这些对象递归组合的对象。

结构:

Posa的114类设计模式_组4、5、6

Composite层级结构的对象可以分为两类叶子和组合体,组合体由叶子和组合体组成,叶子对象实现了原子实体的行为,且不可再分。

优点:1)Composite设计可以用于表现任意的Whole-Part结构,只要其内部的对象实现了组件的接口,2)该结构对客户端透明,客户端只能看到所有的对象遵守一致的契约3)易于升级,进行扩展不必对已有的叶子和组合进行修改。缺点:过于臃肿。

组件结构:

Posa的114类设计模式_组4、5、6

Master—Slave

我们经常需要某种措施来提供系统组件的性能,容错能力或者结果精度。

某些组件必须满足很高的性能,容错能力或者计算精度方面的要求,尤其是那些处理关键和复杂应用的组件。使用更多,更强大的计算资源会有所帮助,但是类似解决方案往往过于昂贵,而且有时候也不充分。解决方法,采用分而治之的策略,来满足性能,容错性或者计算精度方面的需求。将服务划分成独立的、可并行执行的子任务,通过合并这些子任务的返回结果来得到服务的最终结果。

结构:

Posa的114类设计模式_组4、5、6

典型应用:hadoop

缺点:任务必须可拆分,Master通常只有一个,可能会造成单点失败。

Half-Object plus Protocol

我们经常需要减少从多个地址空间访问一个对象的响应时间。

在分布式系统中,我们的设计经常需要允许客户端访问位于其他地址空间的组件内的对象,然而由于跨网络交换请求和响应的时候常会引入延迟和抖动,者使得我们的设计不能使用快速响应的要求(复制会引入网络流量和更新的问题)。解决方法:将这些对象分成多个“半对象”,每个半对象在哪里使用就放在哪个地址空间中,每个半对象值实现它所在地址空间内的客户端所要求的功能和数据,在所有的半对象之间通过一个协议来帮助它们协调动作,并保持状态的一致性。

结构:

Posa的114类设计模式_组4、5、6

优点:网络应用降低,性能提高,可伸缩性好。

缺点:数据和功能的重复(客户端地址空间可以本地执行的功能越多越好)。

Replicated Component Group

我们有时候必须为组件的实现提高容错能力和高度的可靠性。

系统中的有些组件必须满足高可靠性和高容错性的需求,尤其是那些复杂执行和协调集中活动的组件。大多数系统中,只有少数几个组件需要极高的可靠性和容错能力,不适合使用硬件的系统解决方案,组件必须在一个虚弱的环境中保持自身的强壮。解决方法:提供一组,而不是一个组件的实现,将这些组件的实现复制件分布到不同的网络节点上。将客户端在组件接口上的请求转发给所有实现的实例,并等待其中某个实例返回执行结果。

将组件组所有的实例中返回的第一个结构返回给客户端。

结构:

Posa的114类设计模式_组4、5、6

优点:强大的组件容错能力(组件实例只要有一个能访问即可正常运行),和系统可靠性(一个组件实例负载过重时,低负载组件仍然可以服务这个请求)。

缺点:要求所有的组件的实例要维护一致的状态。

组件结构:

Posa的114类设计模式_组4、5、6

第六章 应用控制

用户界面和其他方面的功能分类需要考虑的问题:

1) 数据结构解耦

2) 位置解耦

3) 工作流解耦

4) 技术解耦

5) 对请求进行显示的协调和控制

6) 安全

Page Controller

在开发MVC架构时,如果视图相对模型是远程的,则对于基于表单的用户界面,我们需要一种机制能够将特定表单所发出的服务请求的处理和执行联合起来。

有些应用提供了介于表单的用户界面,每个表单会调用一套内聚的、相互关联的应用功能。如果对每种类型的客户请求使用一个单独的控制器进行封装,会导致控制器的复杂化,而且如果对来自某个表单的请求的处理有统一的地方也会出现功能重复。解决方法:为应用的用户界面中每个表单引入一个页面控制器以控制该表单上发出的所有请求的执行。

结构:

Posa的114类设计模式_组4、5、6

来自一个表单的所有客户端请求通过与之关联的页面控制器传递个应用,页面控制器将客户端请求转化为对应组件的具体请求。

部署方式:针对客户端(可伸缩性更好,但是客户端有专门的资源进行处理)针对应用(多个客户端共享的话,可能需要同步)。

Front Controller

视图相对模型是远程的时候,对于发生给某个应用的服务请求的处理和执行,往往需要一种机制能够把他们联合起来。

网络应用在处理请求时经常执行一些相似的操作,包括在执行动作之前或者之后进行授权和记录日志,根据当前的情况为特定的用户显示特定的视图。如果在应用的每个控制器中各市县一套这些功能就会出现很多重复代码,从而使得代码难以维护和改进。解决方法:引用一个Front Controller 专门负责发布应用的功能,并将客户端的服务请求转化为具体的可以在应用组件上调用的请求。

结构:

Posa的114类设计模式_组4、5、6

所有的客户端请求都有Front Controller进行分派。优点:通用的请求处理代码容易维护与改进,内存占用降低,而且提供授权与日志等辅助功能缺点:集中式设计可能会造成性能和扩展瓶颈,容易单点失败。

结构:

Posa的114类设计模式_组4、5、6

Application Controller

为了处理用户界面导航和应用的工作流,我们必须提供一个访问点。

应用往往让用户根据某个工作流 访问一系列的页面和表单,或者某个条件下能看到某些页面和表单。但是这些逻辑应该与用户界面代码和应用的工作流逻辑分离。解决方法:将应用的工作流单独封装到一个Application Controller中。用户界面使用该Application Controller来决定调用应用逻辑中的那个动作,已经动作执行完成之后显示那个视图。

结构:

Posa的114类设计模式_组4、5、6

Application Controller为用户界面元素提供了一个集中的访问点,将对应用功能及其工作流访问统一在一起。

优点:应用的核心逻辑独立于用户界面结构在内的所有方面,同时用户界面控制器及其视图也独立于工作流和应用逻辑的状态。缺点:潜在性能和伸缩性瓶颈,单点失败。

Command Processor

我们需要一种执行服务请求的机制。

如果一个应用可以从多个客户端接收请求,我们就需要一种机制来管理这些请求的执行。通常独立的客户端不会知道其服务请求应该在何时或者何种条件下执行。解决方法:引入一个Command Processor 专门负责执行服务请求。Command Processor在应用的约束下代表客户端执行请求。

结构:

Posa的114类设计模式_组4、5、6

Command Processor可以访问组件状态信息,也可以执行一些辅助功能或者系统管理功能。组件的客户端本身不需要关心如何组织具体的服务请求的执行了,降低了两者间的耦合度。客户端不能够直接调用组件上的功能了,只能通过对象化的请求来由Command Processor执行组件上的请求。

使用:

Posa的114类设计模式_组4、5、6

Template View

我们需要某种预先指定的视图格式来展示应用数据或者其他信息。

我们经常需要在应用中以各种视图来展示动态的数据。这些视图每一次显示或者更新其内容都会发生变化,要想为每种可能的变化做一个单独的视图实现,会使得代码无限膨胀。解决方法:引入一个Template Vie,在这个Template View中预先定义好视图结构,并为动态的数据设置好占位符。

结构:

Posa的114类设计模式_组4、5、6

Transform View

我们经常需要把应用返回的请求响应数据转换为适当的视图

应用一般都是通过多个视图将由应用服务器返回的内容展现给用户,这些内容往往来自不同的、复杂的数据结构,通常这些数据结构并不包含关于那些内容字段应当显示或者应当以什么样的形式显示的信息,同时视图内部实现数据检测会导致应用逻辑与节目耦合,此外,数据检测和转换的代码越大,越不适合于低配置的瘦客户端。解决方法:引入一个Transform View,通过它变量从应用中返回的数据结构,找到需要显示的数据,并将其转换成合适的输出格式。

结构:

Posa的114类设计模式_组4、5、6

优点:使得数据检测逻辑与实体显示相关数据呈现代码分离,也可以作为可插拔的组件存在。缺点:转换逻辑本身就是代码,缺少必要工具支持,测试和调试困难。

使用:

Posa的114类设计模式_组4、5、6

Firewall Proxy

我们必须保护组件免受外来的攻击。

如果一个应用可以通过互联网等公共网络访问,通常他不知道谁在使用它,所以本质上任何人都可以调用其功能。因此我们需要保护这些应用,以防止来自客户端的服务请求中嵌入工具代码。解决方法:为应用可以公开访问的功能引入一个Firewall Proxy,通过这个Proxy为每个客户端添加相应的安全策略,从而保护了实现该功能的组件免受攻击。

结构:

Posa的114类设计模式_组4、5、6

外部客户端只能通过Firewall Proxy访问组件。

使用:

Posa的114类设计模式_组4、5、6

Authorization

我们必须确保只有特定的客户端可以访问某个子系统的功能。

子系统必须为其客户端提供定义良好和有意义的功能。否则它对客户端来说就没什么价值。客户端可以通过发送服务请求来调用这些功能,但是不是所有的可以向子系统发送请求的客户端都有权调用这些功能。解决方法:如果一个子系统本身是绝对安全敏感的,在客户端向其发送服务请求的时候,为客户端分配合适的访问权限,并在子系统执行每个请求前检查这些权限。

结构:

Posa的114类设计模式_组4、5、6

优点:子系统只能被授权的客户端访问,访问权限和检查策略可以被透明的改进,不会对应用的客户端组件产生任何影响。

使用:

Posa的114类设计模式_组4、5、6

读书人网 >操作系统

热点推荐