组合模式用于统一处理树形结构中的个体与容器,外观模式用于简化子系统对外接口;二者解决不同问题,混用会导致设计僵化。

组合模式和外观模式解决的是两类完全不同的问题:组合模式用于统一处理树形结构中的个体与容器,外观模式用于简化子系统对外的交互接口。混用或误判场景会导致设计僵化、职责错乱。
什么时候该用 Composite 而不是继承或集合
当你有一组对象天然存在“部分-整体”层级关系,且希望客户端代码无需区分单个对象和一组对象时,Composite 才真正必要。常见误用是把普通列表包装成 Composite,结果徒增抽象层却无实际收益。
- 必须让叶子(
Leaf)和容器(Composite)实现同一接口(如Component),否则无法递归调用 -
add()、remove()、getChild()等操作在Leaf中应抛出UnsupportedOperationException,而不是静默忽略——这能尽早暴露误用 - 避免在
Composite中暴露内部集合(如返回ArrayList引用),应只提供不可变视图或封装遍历逻辑
public interface Component {
void operation();
void add(Component c);
void remove(Component c);
}
public class Leaf implements Component {
public void operation() { / 具体行为 / }
public void add(Component c) { throw new UnsupportedOperationException(); }
public void remove(Component c) { throw new UnsupportedOperationException(); }
}
Facade 不是“写个工具类”的代名词
Facade 的核心价值在于解耦:它不隐藏功能,而是收敛调用路径。如果只是把几个静态方法塞进一个类,没做协调逻辑、没屏蔽子系统依赖、没统一异常处理,那只是命名空间整理,不是外观模式。
- 一个
Facade类通常只持有一组子系统类的引用,不继承、不实现子系统接口 - 方法签名应面向使用场景(如
processOrder()),而非子系统能力(如inventory.check() + payment.charge() + notify.send()) - 若
Facade方法开始接受大量参数、或需要调用方预先构造子系统对象,说明边界已泄漏,应重构
public class OrderFacade {
private final InventoryService inventory;
private final PaymentService payment;
private final NotificationService notification;
public OrderFacade(InventoryService inventory, PaymentService payment, NotificationService notification) {
this.inventory = inventory;
this.payment = payment;
this.notification = notification;
}
public boolean processOrder(Order order) {
if (!inventory.checkStock(order)) return false;
if (!payment.charge(order)) return false;
notification.sendConfirmation(order);
return true;
}}
成新网络商城购物系统
使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888
下载
立即学习“Java免费学习笔记(深入)”;
组合与外观一起用的典型场景
当你要对外暴露一个“可嵌套配置的复杂组件”,又希望使用者不必了解其内部模块协作细节时,两者才自然交汇。例如 UI 框架中一个可折叠面板(CollapsiblePanel):它既是 Component(可被加到布局树中),又封装了动画、事件代理、DOM 更新等子系统。
-
CollapsiblePanel实现Component接口,支持addChild()、render(),体现组合特性 - 但它内部通过
AnimationFacade、EventFacade协调底层库,使用者无需知道用的是requestAnimationFrame还是 CSS transitions - 关键分界:组合定义“它是什么结构”,外观定义“它怎么和别人合作”
真正难的是判断哪一层该抽象、哪一层该封装。组合模式容易过度设计成深树,外观模式容易退化为大杂烩类——它们的价值不在代码是否存在,而在是否让调用方少写一行 if (obj instanceof Composite),或少记三个子系统初始化顺序。









