这一服务规范稍微有些复杂,这是因为被提供和被要求的服务的功能性必须以一个指定的顺序被调用和响应。在这种情况下,一个活动习惯于定义服务协议。然而,这只是一个选择问题;我们可以使用交互作用或者状态机。
图6显示了 Purchasing 服务规范:

图6. Purchasing 服务规范
Purchasing 服务规范反映了在初始的 Process Purchase Order 业务过程中被指定的功能性。它反映了一个被指定和设计的服务来实现业务过程。由于没有于这一规范相关联的服务协议,所以我们再一次使用套用的接口对其进行建模。
至此,我们已经准备好设计提供给每一项服务的组件。
服务实现
服务定义了一组由服务提供者所提供的功能,这些功能满足了服务消费者或者用户的需要。服务实现设计的第一步,就是供应服务。也就是说,指明哪一个服务提供者将提供什么服务功能。这是设计 SOA 的关键部分,这是因为选择提供者建立了服务消费者和提供者之间的关系。因此,这就建立了系统的功能以及各部分之间的耦合。
您可以将所有这些操作放入到一个单一的服务中,拥有一个单一的解决方案。但是所有客户端都将依赖于一个服务,这就将导致一个非常高度的耦合。提供者的任何改变都将导致所有消费者的改变。这是早期 C 编程时代里常见的模块库问题。您也可以为每一项功能创建一个独立的服务,但是这就将导致一个非常复杂的系统,并且它不会表现出很好的封装性和内聚性。它也很难在共同遵循一个协议来使用一组相关功能的消费者和提供者之间进行建模。
最后,决定服务参与方需要一些技巧,会被许多因素所影响和制约。分发能够扮演一个关键的角色。如果我们能够设计出独立于消费者和提供者位置的 SOA 解决方案的话,将非常有意义,但是通常来说这并不现实。服务被配置在哪里,是同消费者和其他被需要的服务相关的,并且对解决方案的性能、适应性、和安全性具有非常重大的影响。在解决方案的体系结构中忽略这一点,可能导致不可接受的解决方案的实现。
此处,我们的问题相当简单,所以决定服务参与方将提供或者消费什么服务并不十分困难。下一小节将提供图2中所显示的所有服务的提供者的模型,以及图下面详细的服务规范。这是一个相当简单的例子,许多服务提供者仅仅提供一项只具有一种功能的服务。这种情况并不常见。服务提供者通常要提供或者消费(或者两者皆是)许多服务,每项服务具备许多种功能。我们的例子只是关注概念,而不去纠缠例子本身的细节。
货品计价
货品计价服务提供者为计算订货单的初始价格提供 Invoicing 接口,当交付信息得到之后,它重新定义这一价格。订购者的全部价格取决于产品在哪里生产,以及它们从哪里被交付。最初的价格计算可能被用来验证消费者有足够的信用或者仍然想要购买该产品。在完成定购前对此进行验证显然要好的多。
我们对服务提供者进行的设计,首先创建一个定义其需求的系统用例,以及一个被称作 Invoicer 的实现该用例的 <serviceProvider> 组件。货物组件将会在信用包中,该包导入 CRM (消费者关系管理)来使用普通服务数据(消息)定义。图7显示了我们所做的所有工作。

图7. 初始的 Invoicer 服务提供者
Invoicer 服务提供者将提供 InvoicingService 服务。我们通过添加一个 <service> 端口到 Invoicer 中(它的类型是 InvoiceService 服务规范)来对其进行建模。所有的服务都由服务规范输入,这些规范定义了哪些功能性被提供和要求,以及使用它们的协议。图8展示了添加了货品计价服务的 Invoicer。

图8. 添加一个 InvoicingService 到 Invoicer 服务提供者