67

我读得越多,我就越困惑。

请注意,所有问题都与服务和外观如何适应 MVC 模式有关。

我的理解是,Facade 并不是一个超级智能的对象,它只是暴露一个简单的接口/api 来执行复杂操作的一种方式(例如:执行 10$ 支付,它是一个复杂的操作,涉及到许多操作,但是这样的复杂性可以由一个外观来处理,它只会以特定的顺序调用相应的对象......等等......)

现在,服务是一种调用多个 DAO 以获得复杂数据结构的方法(我不太确定,但这是我目前所理解的)。

那么问题是,门面和服务之间有什么区别?归根结底,Facade 可以通过提供简单的接口完美地访问多个 DAO 以执行复杂的操作,而服务似乎类似于类似的东西。

事务也是如此,我知道服务是开始事务的地方,但我同样觉得它们也可以放在门面上,毕竟门面也可以调用多个 DAO。

所以哪个堆栈更有意义

控制器外观道控制器服务道

或者可能

controller-facade-dao 有时还有控制器-facade-service-dao ??

4

11 回答 11

60

服务是一种编写外部系统接口的方式,例如 LDAP 身份存储、支付网关或应用程序管理接口。这是一种将外部系统视为有用服务提供者的概念方式,可能具有内部行为,而不是要操作的被动块。

外观是一种包装任何东西(包括服务)以将其很好地呈现给另一个组件的方式。立面通常在以下情况下使用:

  • 库或组件很复杂,您的应用程序只需要其中的一个子集。您的 Facade 将简化的 API 呈现给应用程序
  • 您正在使用多个库或组件,需要统一它们,为应用程序提供统一的 API
  • 您正在使用的库具有复杂的设置或一组依赖项,并且外观将所有这些都包装在您的应用程序的上下文中。

真正令人困惑的一点是,您可以(并且经常这样做)在一个或多个服务上创建一个外观。服务是组件实际访问资源的方式,门面是简化组件的位(例如选项的配置、连接等)。

如果您编写自己的 DAO,您可能会根据需要创建服务,因此编写外观表明您做错了。如果 DAO 是由第三方构建的,并且比您的需要更复杂,那么您可以外观服务。

现在,服务是一种调用多个 DAO 以获得复杂数据结构的方法(我对此不太确定,但这是我目前所理解的)。

我会说 DAO 本身就是一种设计模式 -请参阅 wikipedia

如果我们将 DAO 与服务进行对比,我们有:

  • API级别:
    • DAO:对属性的细粒度访问
    • 服务:粗粒度访问服务
  • 实施所在:
    • DAO:主要在客户端,但在数据库中存储数据(没有行为)
    • 服务:主要在服务器上
  • 如何调用接口
    • DAO:客户端直接绑定到与JVM相同命名空间的对象
    • 服务:客户端只是网络、跨虚拟机或跨命名空间操作的存根

...外观可以通过提供简单的接口完美地访问多个 DAO 以执行复杂的操作,并且服务似乎类似于类似的东西。

外观可以包裹 DAO 层,但我并没有真正看到这种情况以一种有用的方式发生。您很可能需要一个 API 来访问对象的各个属性、遍历对象图等,而这正是 DAO 提供的。

交易也是如此,我知道服务是开始交易的地方......

绝对可以,因为事务是由数据库和另一个组件或系统提供的服务

...但我同样觉得它们也可以放在外观上,毕竟一个外观也可以调用多个 DAO。

并且在许多方面,事务管理器服务是一个更复杂的后端实现的门面,协调 Web、应用程序、数据库和其他事务感知组件上的事务。然而,这已经被事务服务实现抽象掉了。就我们用户而言,只有公共界面。

事实上,这就是这些设计模式的概念点——为用户提供恰到好处的 API,将实现的复杂性抽象化在组件接口的铁墙后面。

所以哪个堆栈更有意义

控制器外观道控制器服务道

或者可能

controller-facade-dao 有时还有控制器-facade-service-dao ??

  1. DAO 是一种对数据库的服务,但实际上 DAO 本身就是一种设计模式。
  2. 如果您编写自己的 DAO,则永远不需要外观。

因此正确答案是:

  • 控制器 - 道
于 2013-02-26T01:47:41.310 回答
27

从字面上看,Facade 顾名思义就是建筑物的正面。路过的人只能看到立面,他们对里面的东西、布线、管道和其他复杂的东西一无所知。面孔隐藏了建筑物的所有复杂性,并显示出更简单友好的面孔。

在软件方面,Facade 通过提供更简单的界面隐藏了软件组件的复杂性,它没有自己的功能并且不限制对 substsyem 的访问。常用于面向对象设计。很好的例子是 SLF4J - 它是一个 api,它是日志系统的简单外观,允许最终用户在部署时插入所需的日志系统。

服务是提供对功能单元的访问并始终写入规范的公共接口。它需要支持其不同消费者所需的通信契约(基于消息的通信、格式、协议、安全性、异常等)。流程服务- 业务工作流程的封装,业务逻辑服务- 规则/功能的封装,数据服务- 与实体的交互,数据访问管理,基础设施服务- 实用功能,例如监控,日志记录和安全性。服务大多是可重用的、不相关的、松散耦合的功能单元。

它们非常相似,但取决于您如何看待它。

我看到的不同之处在于,外墙是由内而外设计的。您查看子系统并设计一个外观以提供更简单的访问。服务是由外而内设计的。您查看您的客户/客户定义合同并设计服务。

于 2013-02-26T08:51:30.393 回答
6

我对经典 GoF Facade 模式的理解是,它主要是为了隐藏糟糕的设计。根据经验,我会说一个人应该只需要一个 Facade 来处理遗留代码。

我还认为这种模式成为 J2EE 核心模式(会话外观)主要是因为 EJB 规范(至少到 2.x)固有地导致了糟糕的服务层设计。

因此,我对您的问题的回答是肯定的——外观实际上是第一次没有正确实施的服务。如果您需要隐藏客户端代码的复杂性,通常意味着您只设法提供了一个库,而不是一个服务层;所以,在这种情况下,Facade 实际上变成了你的服务层。

另一方面(假设您有一个不错的域层),如果您确实需要提供通过单个方法调用(类似于宏/别名)生成复杂流的选项,这通常会更好地放置在应用程序层和不在您的核心领域——请注意,我已将分层术语切换为领域驱动设计,其中没有“数据访问”或“服务”层,而是“应用程序”、“域”、“基础设施”

于 2013-03-01T22:29:11.307 回答
3

FACADE 是一种设计模式,它解决了子系统中的许多接口需要统一接口的问题,因此它定义了一个更高级别的接口,使子系统更易于使用。

但是,服务提供对资源或一组接口/对象的访问,可能不一定会简化这种访问。因此,您可以使用外观模式来更好地设计您的服务,这样您就可以节省客户弄清楚如何构建以使用它的时间。

于 2013-03-04T16:44:49.850 回答
2

在我尝试回答之前,让我澄清一下:企业应用程序中存在三个不同的东西 - FacadeService LayerRemote Facade

外观- 在包装子系统时,仍然是一个对象,并且 UI (MVC) 应用程序通常存在于同一个进程中。因此,通信以通常的 OO 方式完成:调用方法、读取属性、监听事件。

服务层- 当业务逻辑层变得成熟且过于复杂以至于 MVC 无法直接与其交互时,则将服务层置于它们之间。服务层是 MVC 用作业务逻辑包装器的 API。它不是远程的,也不需要使用 DTO,因为通信中不涉及电线。

Remote Facade -(简单来说,任何远程服务)这是 Facade 和服务层的混合体。当您想要在系统上公开某种包装器(我们称之为 Facade)作为分布边界时,远程 Facade 就开始存在。原因之一可能是允许多个 UI (MVC) 应用程序使用相同的远程外观。

-

比较:

外观服务层:它们是相似的,因为它们都包装了子系统。不同之处在于服务层更面向 UI (MVC) 应用程序需求,并公开功能以简化业务逻辑的使用。另一方面,Facade 正在公开功能以简化业务逻辑,但不一定简化与 UI (MVC) 应用程序的通信。

Facade vs. Remote Facade(服务?):绝对不同,因为 Remote Facade 必须使用 DTO 作为通信消息。如果您仍想将 Remote Facade 用作常规对象(属性、事件),则远程 Facade 将需要某种代理;但是代理无论如何都会对真实对象使用 DTO,即远程外观。

-

可能的流量:

controller-facade-dao- 值得怀疑,但仍有可能。Facade 通常不用于包装 DAL。除了作为子系统之外,应该还有一些更成熟的东西。但是,如果外观是业务逻辑的一部分,那么是的,这是可能的。仍然必须更加强调子系统。对我来说,DAL 包装不足以称之为 Facade。

controller-service-dao- 绝对有可能。许多远程服务通过 DAL 直接使用数据库。

controller-facade-service-dao- 也许,如果您将服务视为子系统。

我会再添加一个有意义的:

controller-service [layer]-facade (part of business)-subsystem (e.g. accounting, business on its own)-dao- 我相信你可以翻译这个。

-

请记住,服务(或远程外观)可以存在于流程中的任何位置。这只是由您的分发需求决定的。

于 2013-03-01T18:30:43.687 回答
2

首先要注意的是,设计模式是对具有标准解决方案的常见(设计)问题的描述。在某些情况下,有多种方法可以满足所有需求(例如,迭代器和单例模式有大量不同的实现;例如,检查工作Alexandrescu并将其与标准 GoF 解决方案进行比较)并且在某些情况下,具有相同(代码)解决方案的不同模式(例如,比较 GoF 书中的 Composite 和 Decorator 模式的类图)。

根据 GoF,外观模式的目的是(字面引用):

为子系统中的一组接口提供统一的接口。Facade 定义了一个更高级别的接口,使子系统更易于使用。

服务旨在为用户提供具有给定功能的单个更高级别的界面。这并不一定使它成为一个门面,因为严格来说,服务不是按照定义unified interface to a set of interfaces in a subsystem.

但我们可以做得更好

您的问题是模式是否“相似”。如果当模式 A 等于 B 且模式 B 等于 A 时我们认为它们“相似”,那么我们应该回答 2 个问题:

问题 1:ServiceaFacade吗?服务绝对应该公开功能,并且绝对是公开此功能的单个接口。功能通常被分解成小块,所以是的,服务符合外观的基本要求。换句话说:面对将底层接口暴露为统一的“服务”接口的问题,门面模式符合需求,用于解决服务问题。答案是肯定的。

问题 2:FacadeaService吗?服务通常被设计为可重用、无关联、松散耦合的功能单元。考虑组件之间的通信对于服务来说很重要,因为它们通常依赖于 TCP/IP 接口,例如 SOAP 或 WCF。这也意味着功能经常被重写以services更接近范式,这增加了模式的性能要求的隐含驱动。外墙没有这个额外的要求。换句话说:门面不是服务

确切地说,这些概念密切相关,但并不相同。

但我们可以做得更好

这种思路提出了一个问题,如果服务是外观的扩展版本?如果服务满足外观的所有要求并在此基础上进行扩展。

如果仔细阅读 GoF 的描述,答案是肯定的,即:如果满足一个条件:服务必须暴露子系统。实际上,我认为这种情况通常成立,或者您过度设计了您的服务 - 尽管严格来说我认为这不是一个硬性限制。

于 2013-02-27T15:31:19.963 回答
2

通常,这些术语仅在其特定上下文中使用。

  • 'Facade' 常用上下文:应用程序复杂部分的简单 API(如第三方库)

  • “服务”上下文:解锁并显示系统中的业务实体。(SOA、DAO、安全等)

您可以将模式视为一种不断发展的语言。似乎从来都不是完美的结局,每种模式都有自己的历史和背景。有时类可以同时被视为服务和外观,有时不是。

例如:由于上下文错误,通过术语“服务”调用第三方 API 可能被视为滥用。

于 2013-02-23T20:47:24.963 回答
1

服务接口通常代表业务关注点:执行一些操作和/或获取一些信息。服务提供商将他们的服务实现为内部后端服务的外观并不是不合理的 - 你永远不会看到这一点。

您的外观可能包含一些通用接口,其中可能包括服务接口。

例如,您可能有银行账户的服务接口(操作:银行转账),以及本地会计记录的本地 API(我转账)。您可能会通过使用银行的服务接口并管理您的本地支票簿的“转移资金”操作来引入外观。

于 2013-02-26T00:45:25.767 回答
1

是的,Facade 和 Service 并非完全无关。有时我们将服务层实现为外观,这样客户端就不会为服务的许多细节而烦恼。服务的调用/接口越简单,客户端代码就越简单。

马丁福勒说……

服务层从连接客户端层的角度定义了应用程序的边界 [Cockburn PloP] 及其可用操作集。它封装了应用程序的业务逻辑,在其操作的实现中控制事务和协调响应

所以服务层有时被用作外观。

参考

于 2013-02-26T04:52:12.873 回答
1

重要的是“上下文”。外观和服务并不冲突。

首先,我从未听说过 MVC 上下文中的“服务”和“外观”。

当人们谈论服务时,它更多地是关于向外部世界提供具有业务意义的操作的系统或组件。您有时可能会看到与“工作单元”(因此也就是事务)相关的“服务”。

Service 也用于应用程序的一些分层方法的上下文中:我们在 DAO 之上有 Service,Service 将通过 DAO 访问数据,并将业务逻辑放在 Service 层中,类似这样。

Facade通常用于设计模式的上下文中,重点是“隐藏复杂的操作,将其暴露为简单的操作”。

Facade 可能是也可能不是 Service(Facade 中的操作可能不代表工作单元,但它仍然是有效的外观),同样,Service 可能是也可能不是 Facade(Service 可能不会隐藏任何复杂的操作,但它仍然是一项服务)。

同样,重要的是“上下文”。

例如,当您谈论应用程序的分层时,说“XXX 是访问 DAO 的门面”简直是不合理的。同样,如果你说的是“设计方法”,在这里说“XXX是多个后端的门面”而不是“服务”更合理(虽然XXX实际上是一个服务)。

于 2013-02-26T03:24:08.003 回答
0

外观服务层有一种相似之处,但它们都有两个不同的含义。让我用一个简单的例子来解释这一点。

想象一下,我们被要求创建新的业务应用程序。这需要创建一个签到应用程序,但具有更多的增值功能和会员卡功能。

如果用户希望使用,假设应用程序应该支持 Facebook 和 Foursquare 签到功能。非常需要此功能,因为一些用户不愿意使用多个应用程序来执行相同的功能或摆脱社交连接。

要获得高级别的想法,请参阅以下链接上的示例 api https://docs.google.com/file/d/0B3v8S0e-PvVpdWFJOVhqc1d2SHc/edit?usp=sharing

上面位于 ABC 门面的签到 API 是使用门面的示例。

它具有我们的服务 API 以及基于客户选择的 facebook 和foursqure 签入功能。Facebook 和foursqure API 可以有特定的实现(SOAP、Restful 等)和安全性(OAuth 等)要求等。

满足其中一个 API(facebook、foursqure)要求需要完成不同的任务集。这些将是我们签入要求中的不同子系统。

所以facade的简单用法就是满足一个简单的方法触发的几个子系统

但是如果我们考虑我们自己的 API,即位于 MngCheckinSvc 的签入 API。这是一个服务层 API。这是包含我们应用程序签入要求的 API。这是从您的 MngCheckinSvc 提供公共访问以处理对应用程序的签入要求的 API。

这将具有复杂的内部行为,但其中大部分仍将是特定于应用程序的逻辑实现。

此 API(MngCheckinSvc.checkin(....)) 可能会访问不同的 DAO 集、内部 API、可能是其他内部服务等,以便在应用程序中完成商家签到。

于 2013-03-03T11:59:57.870 回答