2026年7月11日 · 4 分钟阅读
Java 结构型设计模式:适配器、桥接、装饰者、组合、外观、享元与代理
梳理结构型设计模式如何组织对象关系,以及它们在 Java 项目中的典型使用场景。
结构型模式关注对象之间如何组合。
创建型模式解决“对象怎么来”,结构型模式解决“对象怎么协作成更大的结构”。它通常不改变核心对象本身,而是通过包装、组合、代理、共享等方式增强系统能力。
适配器模式
适配器模式用于解决接口不兼容问题。
例如系统需要统一的支付接口,但第三方支付 SDK 的接口和系统定义不一致,就可以使用适配器。
public interface PaymentClient {
void pay(String orderNo, int amount);
}
public class ThirdPartyPaySdk {
public void submitPay(String id, int cents) {
System.out.println("pay " + id);
}
}
public class ThirdPartyPayAdapter implements PaymentClient {
private final ThirdPartyPaySdk sdk;
public ThirdPartyPayAdapter(ThirdPartyPaySdk sdk) {
this.sdk = sdk;
}
public void pay(String orderNo, int amount) {
sdk.submitPay(orderNo, amount);
}
}
适配器适合对接遗留系统、第三方 SDK、旧接口升级。
桥接模式
桥接模式用于把抽象和实现分离,让两个维度可以独立变化。
例如消息发送有两个变化维度:
- 消息类型:普通消息、告警消息。
- 发送渠道:短信、邮件、企业微信。
如果使用继承组合,会出现大量类。桥接模式可以把渠道抽象出来。
public interface Sender {
void send(String content);
}
public abstract class Message {
protected final Sender sender;
protected Message(Sender sender) {
this.sender = sender;
}
public abstract void notify(String content);
}
桥接模式适合多个维度同时变化的场景。
装饰者模式
装饰者模式用于在不修改原对象的情况下,动态增强功能。
典型例子是 Java IO:
InputStream input = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedInputStream 并不改变 FileInputStream,而是在外层增加缓冲能力。
业务中也可以用装饰者实现权限增强、日志增强、缓存增强。
组合模式
组合模式用于处理树形结构,让单个对象和组合对象具有一致接口。
典型场景:
- 组织架构。
- 文件目录。
- 菜单树。
- 商品分类。
public interface MenuNode {
void print();
}
public class MenuItem implements MenuNode {
public void print() {
System.out.println("item");
}
}
public class MenuGroup implements MenuNode {
private final List<MenuNode> children = new ArrayList<>();
public void add(MenuNode node) {
children.add(node);
}
public void print() {
children.forEach(MenuNode::print);
}
}
组合模式的关键是统一叶子节点和容器节点的处理方式。
外观模式
外观模式为复杂子系统提供一个统一入口。
例如下单流程可能涉及库存、优惠券、支付、物流。调用方不应该直接编排所有子系统,可以通过一个外观服务封装流程。
public class OrderFacade {
public void createOrder() {
// check stock
// lock coupon
// create payment
// notify logistics
}
}
外观模式适合降低调用方复杂度,但不要把所有业务都塞进一个巨大的 Facade。
享元模式
享元模式通过共享对象减少内存占用。
适合大量细粒度对象,并且这些对象内部状态可复用的场景。
常见例子:
- 字符串常量池。
- 数据库连接池。
- 缓存对象。
- 棋子、图标、样式等可复用对象。
使用享元模式时,要区分内部状态和外部状态。内部状态可以共享,外部状态由调用方传入。
代理模式
代理模式通过代理对象控制对目标对象的访问。
常见用途:
- 权限控制。
- 日志记录。
- 延迟加载。
- 远程调用。
- 事务增强。
静态代理示例:
public interface UserService {
void updateUser();
}
public class UserServiceImpl implements UserService {
public void updateUser() {
System.out.println("update user");
}
}
public class UserServiceProxy implements UserService {
private final UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
public void updateUser() {
System.out.println("check permission");
target.updateUser();
}
}
Spring AOP 中大量使用代理思想,用于事务、日志、权限等横切能力。
结构型模式选择建议
| 场景 | 推荐模式 |
|---|---|
| 新旧接口不兼容 | 适配器 |
| 多个维度独立变化 | 桥接 |
| 动态增强对象能力 | 装饰者 |
| 树形结构统一处理 | 组合 |
| 隐藏复杂子系统 | 外观 |
| 大量对象可共享 | 享元 |
| 控制访问或横切增强 | 代理 |
小结
结构型模式的重点是组织对象关系。
当系统中出现接口不兼容、对象组合复杂、横切增强、树形结构、访问控制等问题时,结构型模式通常能让代码边界更清晰。