← 返回题目列表

Service Facade 在项目分层中应该怎么设计?

高频 中等 第 12 / 25 题 更新于 2026/07/28
外观模式Service Facade分层架构应用服务DDD

简化版

Service Facade 通常放在 Controller 和多个业务服务之间,对外提供粗粒度用例接口,对内协调领域服务、基础服务和外部系统。设计时要让 Facade 负责流程编排和边界收口,不要把所有领域规则都堆进 Facade。

详细版

典型分层:

Controller
  -> Facade / Application Service
      -> Domain Service
      -> Repository
      -> External Client

Facade 适合承担:

  • 用例入口;
  • 参数转换;
  • 权限校验入口;
  • 事务边界;
  • 多服务编排;
  • 结果聚合;
  • 异常转换。

不适合承担:

  • 大量领域规则;
  • 底层数据访问细节;
  • 所有业务逻辑堆积;
  • 跨多个边界的万能协调。

好的 Facade 应该让上层调用简单,让下层职责清楚。

完整版教学

一、Facade 在分层架构中的位置

很多 Java Web 项目会有:

Controller -> Service -> Mapper

当业务复杂后,一个 Controller 可能要调用很多 Service。

这时可以增加 Facade 或 Application Service:

Controller -> OrderFacade -> UserService
                          -> StockService
                          -> OrderService
                          -> MessageClient

Controller 只关心一个用例入口。

二、Facade 应该表达用例

Facade 的方法最好是业务用例级别:

createOrder()
cancelOrder()
queryOrderDetail()
submitApproval()
generateReport()

不要把 Facade 写成纯工具集合:

doSomething()
handle()
process()

方法名越贴近业务用例,边界越清楚。

三、Facade 负责流程,领域服务负责规则

Facade 可以组织流程:

userService.check();
stockService.lock();
orderService.create();
eventPublisher.publish();

但“订单能不能取消”“库存怎么扣”“价格怎么算”这类领域规则,最好放在对应领域服务或领域对象里。

否则 Facade 会越来越胖。

四、事务边界可以放在 Facade

如果一个用例涉及多个本地数据库操作,事务边界常放在 Facade 或应用服务层。

@Transactional
public OrderResult createOrder(CreateOrderCommand command) {
    // 编排多个服务
}

这样一个完整用例在同一个事务里执行。

但如果涉及远程服务,不能简单依赖本地事务,要考虑最终一致性、补偿、消息可靠性等问题。

五、Facade 和 Domain Service 的区别

Facade 更偏用例编排,Domain Service 更偏领域规则。

例如:

OrderFacade:创建订单流程
PriceService:计算价格规则
StockService:库存锁定规则

Facade 可以调用这些服务,但不要替代它们。

六、常见误区与追问

Service Facade 应围绕应用用例,而不是简单映射数据库表。一次转账用例含校验、记账、事件3步,事务边界可由 Facade 组织,但余额不可为负等规则应由领域对象保证。这样 Controller 只处理协议,Facade 处理流程,领域层处理不变量。

检查维度判定依据
Service Facade用例编排、事务、权限边界
Domain Service跨实体业务规则与不变量

记忆钩子:Facade 决定“这次用例走哪些步骤”,领域层决定“每一步什么才合法”。

  • 误区:每张表都应有一个 Facade。 外观按业务用例和子系统边界设计,不按持久化表机械映射。
  • 追问:Controller 能直接调用 Domain Service 吗? 简单查询可以权衡,但复杂用例应经应用层保持事务和编排一致。
  • 误区:事务越大越安全。 跨远程调用的长事务会增加锁持有和失败复杂度。
  • 追问:Facade 可以返回领域实体吗? 对外边界通常返回 DTO,避免实体被越层修改和序列化泄漏。
  • 追问:如何避免贫血模型? 把业务不变量和状态变化放回实体或值对象,Facade 只协调它们。

七、加强记忆

Service Facade 是项目里的“用例入口层”:对上简化 Controller,对下编排多个服务。它适合放流程、事务、聚合和异常转换,不适合堆满领域规则。边界清楚,Facade 才不会变成上帝类。