目录

外观模式 (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 就是外观模式的典型应用。合理使用外观模式可以降低系统复杂度,提高代码可读性。