外观模式 (Facade Pattern)
为复杂子系统提供统一的简化接口
目录
概述
外观模式是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。
适用场景
- 简化复杂系统的使用
- 解耦客户端与子系统
- 分层架构中提供层间接口
基础实现
// 子系统 A
public class SubSystemA {
public void operationA() {
System.out.println("子系统 A 操作");
}
}
// 子系统 B
public class SubSystemB {
public void operationB() {
System.out.println("子系统 B 操作");
}
}
// 子系统 C
public class SubSystemC {
public void operationC() {
System.out.println("子系统 C 操作");
}
}
// 外观类
public class Facade {
private SubSystemA systemA;
private SubSystemB systemB;
private SubSystemC systemC;
public Facade() {
this.systemA = new SubSystemA();
this.systemB = new SubSystemB();
this.systemC = new SubSystemC();
}
// 简化操作 1
public void simpleOperation1() {
systemA.operationA();
systemB.operationB();
}
// 简化操作 2
public void simpleOperation2() {
systemB.operationB();
systemC.operationC();
}
}
// 使用
Facade facade = new Facade();
facade.simpleOperation1(); // 无需了解子系统细节实际应用:订单处理外观
// 库存服务
@Service
public class InventoryService {
public boolean checkStock(String productId, int quantity) {
System.out.println("检查库存: " + productId);
return true;
}
public void reduceStock(String productId, int quantity) {
System.out.println("扣减库存: " + productId);
}
}
// 支付服务
@Service
public class PaymentService {
public boolean processPayment(String orderId, BigDecimal amount) {
System.out.println("处理支付: " + orderId);
return true;
}
}
// 物流服务
@Service
public class ShippingService {
public void createShipment(String orderId) {
System.out.println("创建物流: " + orderId);
}
}
// 通知服务
@Service
public class NotificationService {
public void sendOrderConfirmation(String userId, String orderId) {
System.out.println("发送订单确认: " + orderId);
}
}
// 订单外观
@Service
public class OrderFacade {
@Autowired
private InventoryService inventoryService;
@Autowired
private PaymentService paymentService;
@Autowired
private ShippingService shippingService;
@Autowired
private NotificationService notificationService;
public OrderResult placeOrder(OrderRequest request) {
// 1. 检查库存
if (!inventoryService.checkStock(request.getProductId(),
request.getQuantity())) {
return OrderResult.fail("库存不足");
}
// 2. 创建订单
String orderId = createOrder(request);
// 3. 处理支付
if (!paymentService.processPayment(orderId, request.getAmount())) {
return OrderResult.fail("支付失败");
}
// 4. 扣减库存
inventoryService.reduceStock(request.getProductId(),
request.getQuantity());
// 5. 创建物流
shippingService.createShipment(orderId);
// 6. 发送通知
notificationService.sendOrderConfirmation(request.getUserId(), orderId);
return OrderResult.success(orderId);
}
private String createOrder(OrderRequest request) {
return "ORDER_" + System.currentTimeMillis();
}
}
// Controller 使用
@RestController
public class OrderController {
@Autowired
private OrderFacade orderFacade;
@PostMapping("/orders")
public OrderResult createOrder(@RequestBody OrderRequest request) {
// 客户端只需调用外观方法,无需了解复杂流程
return orderFacade.placeOrder(request);
}
}框架中的应用
Spring MVC DispatcherServlet
// DispatcherServlet 是前端控制器外观
public class DispatcherServlet extends HttpServlet {
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) {
// 简化了处理请求的整个流程
// 1. 获取 Handler
// 2. 获取 HandlerAdapter
// 3. 处理请求
// 4. 处理异常
// 5. 渲染视图
}
}JDBC 操作外观
// JdbcTemplate 是 JDBC 的外观
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
// 简化复杂的 JDBC 操作
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
id
);
}
}SLF4J 日志外观
// SLF4J 是各种日志框架的外观
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyService {
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
public void doSomething() {
logger.info("开始执行");
// 底层可能是 Logback、Log4j2 等
}
}外观与代理的区别
| 外观 | 代理 |
|---|---|
| 简化复杂接口 | 控制对象访问 |
| 聚合多个子系统 | 包装单个对象 |
| 目的是易用性 | 目的是控制 |
优缺点
| 优点 | 缺点 |
|---|---|
| 简化接口 | 可能成为上帝类 |
| 解耦客户端和子系统 | 增加间接层 |
| 提高可维护性 |
总结
外观模式是简化复杂系统的有效手段。在微服务架构中,API Gateway 就是外观模式的典型应用。合理使用外观模式可以降低系统复杂度,提高代码可读性。