Skip to content

P88 面试必问:外观和组合模式到底怎么选? ​

面试题:外观模式(Facade)和组合模式(Composite)有什么区别?各自怎么用?

1. 两个模式定位完全不同 ​

对比项外观模式 Facade组合模式 Composite
目的简化接口:给复杂子系统提供统一入口树形结构:让叶子与容器对象一致对待
解决的问题客户端调用太繁琐/耦合子系统整体-部分层次结构(树)
结构门面类包装多个子系统叶子 + 容器,递归组合
典型场景Service 层聚合多个组件、SDK 封装菜单树、文件系统、组织架构树

2. 外观模式(Facade) ​

text
客户端 → Facade(门面)→ 子系统 A / B / C
java
// 下单门面:一个方法搞定 校验 + 库存 + 支付 + 通知
public class OrderFacade {
    private final StockService stockService;
    private final PayService payService;
    private final NotifyService notifyService;

    public void createOrder(Order order) {
        stockService.deduct(order);
        payService.pay(order);
        notifyService.send(order);
    }
}

价值:

  • 客户端只依赖 Facade,不直接碰一堆子系统;
  • 降低耦合、简化调用;
  • 典型:Service 层对外提供粗粒度方法、SDK 门面。

3. 组合模式(Composite) ​

text
Component(抽象:叶子 + 容器共同接口)
├── Leaf(叶子:文件/菜单项)
└── Composite(容器:目录/菜单,可包含子节点)
java
public interface MenuComponent {
    void show();
}

// 叶子:菜单项
class MenuItem implements MenuComponent { ... }

// 容器:菜单(可以继续装菜单项或子菜单)
class Menu implements MenuComponent {
    private List<MenuComponent> children = new ArrayList<>();
    public void add(MenuComponent c) { children.add(c); }
    public void show() { children.forEach(MenuComponent::show); }
}

价值:

  • 客户端用统一接口操作叶子与容器,递归结构天然适配树;
  • 典型:文件系统、菜单树、组织架构、分类树。

4. 怎么选 ​

  • 想简化一堆复杂组件的调用 → 外观模式;
  • 想表达树形整体-部分结构,且希望叶子/容器一致处理 → 组合模式;
  • 两者不冲突,可以组合使用:外观聚合多个服务,组合表达层级数据。

5. 加分点 ​

  • 说出"外观模式重在封装与解耦,组合模式重在递归树结构",一句话区分;
  • 举源码例子:MyBatis 的 SqlSession(外观)、Spring 的 CompositeCache 等;
  • 追问"装饰器和组合模式区别":装饰器是"包装增强",组合是"树形聚合"。

一句话总结 ​

外观模式给复杂子系统提供一个简化入口(重在解耦),组合模式用树形结构让叶子与容器统一处理(重在递归层级);按"要简化调用还是要表达树结构"来选择,二者可叠加使用。

基于 VitePress 重建