【问题标题】:Are the roles of a service and a façade similar?服务和外观的角色是否相似?
【发布时间】:2013-02-08 21:44:20
【问题描述】:

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

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

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

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

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

事务也是如此,我知道服务是开始事务的地方,但我同样认为它们也可以放在外观上,毕竟一个外观也可能调用多个 DAO。

那么哪个堆栈更有意义

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

或许

controller-facade-dao 有时还有 controller-facade-service-dao ??

【问题讨论】:

  • Façade 一般应用在业务上,使你的应用程序的 api。数据服务只是您的服务。除此之外,您可以在代码中的许多地方使用 Façade。制作 SAL。所以它变成了一个服务访问Api。 Façade 是 Api 的一种模式。
  • Facade 和 A 服务之间的主要区别在于服务实际上做了一些事情,即类定义实际上包含执行某些逻辑的管道。除了将实际工作委派给管道中的服务所需的任何内容之外,IMO 干净的外观不应该包含任何逻辑。
  • 通过使用控制器 dao,您无需将请求处理与逻辑分开。通常使用门面将 dto 对象转换为实体,并使用 dao 来持久化数据。 dao 类从实体中分离出 dto 对象和控制器。业务逻辑也在具有单一职责的外观中执行。 controller-facade-dao 是必须的,也可以使用服务..

标签: java spring model-view-controller design-patterns facade


【解决方案1】:

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

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

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

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

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

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

我会说 DAO 是一种完全独立的设计模式 - see wikipedia

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

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

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

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

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

当然,因为事务是数据库提供的服务,在另一个组件或系统上

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

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

事实上,这就是这些设计模式的概念点 - 为用户提供适量的 API,抽象出组件接口铁墙背后的实现的复杂性。

那么哪个堆栈更有意义

controller-facade-dao 控制器-服务-dao

或许

controller-facade-dao 有时还有 controller-facade-service-dao ??

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

因此正确答案是:

  • 控制器 - 道

【讨论】:

  • 一般我喜欢把 DAO 看成是一个非常原子的元素(例如一个 UserDAO 对象可能有一个 getUserById() 方法),它们是高度内聚的,所以为了执行某些操作(例如向用户付费可能涉及获取用户、获取他的银行账户等)最终调用多个 DAO 的情况并不少见,为这种情况提供 Facade 不是更好吗?
  • 您对凝聚力的观察至关重要——您必须公开这些细粒度的方法,DAO 才能对应用程序有用(您很可能在应用程序中有一个页面供查看或编辑这些属性)。然而,Facade 的意图是完全隐藏这些方面,所以如果你有时直接在它后面,这似乎是不正确的。一定要添加一个辅助方法来包装诸如“支付”之类的操作,但这是一个辅助方法而不是外观。
  • 已了解,但是,Facade 和 Helper 方法之间的核心区别是什么,最后像 payUser() 这样的方法可以完美地成为 FacadeUser 类的一部分,不是吗?
  • 归根结底,一切都是代码——设计模式只是讨论如何组织代码的简单方式,并以其用途命名。这在与同样“认同”这个想法的其他人交谈时很有帮助。是行话。外观是帮助方法的集合,其目的是对应用程序隐藏一个库或一组库(建筑物的外观隐藏它背后的丑陋部分)。所以在一个层面上你是对的,但如果你确实访问了其余部分,那将破坏名称的目的,从而使其他开发人员感到困惑,因此行话不再有帮助。
【解决方案2】:

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

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

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

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

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

【讨论】:

  • 谢谢 user395072,我找不到更好的词来描述这些差异。 “Facades .. 提供了一个更简单的界面,没有自己的功能,也不限制对子系统的访问,...,服务大多是可重用的、不相关的、松散耦合的功能单元。”指出了这一点。 :)
  • 很好,简单的解释。
【解决方案3】:

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

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

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

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

【讨论】:

  • 使用外观来管理版本控制对您有意义吗?相同的 API?
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

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

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

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

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

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

    【讨论】:

    • “有时类可以同时被视为服务和外观”我认为就是这样。服务可以在 Façade 中。 @+1 你解释的很清楚。
    【解决方案6】:

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

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

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

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

    但我们可以做得更好

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

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

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

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

    但我们可以做得更好

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

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

    【讨论】:

      【解决方案7】:

      在我试图回答之前,让我澄清一点:企业应用程序中有三个不同的东西 - FacadeService LayerRemote Facade强>。

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

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

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

      -

      比较:

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

      FacadeRemote 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 - 我相信你可以翻译这个。

      -

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

      【讨论】:

        【解决方案8】:

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

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

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

        【讨论】:

          【解决方案9】:

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

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

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

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

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

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

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

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

          【讨论】:

            【解决方案10】:

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

            马丁·福勒说……

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

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

            Ref

            【讨论】:

              【解决方案11】:

              FacadeService Layer 有点相似,但它们都有两个区别的含义。让我用一个简单的例子来解释一下。

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

              假设应用程序应该支持 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、可能是其他内部服务等,以便在应用程序中完成商家签到。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-02-26
                • 2021-10-20
                • 1970-01-01
                • 2022-11-02
                • 2018-11-05
                • 2023-03-20
                • 2015-12-21
                相关资源
                最近更新 更多