【设计模式手册023】外观模式 - 如何简化复杂系统
1. 我们为何需要外观模式?
在软件设计中,我们经常会遇到这样的场景:一个系统由多个复杂的子系统组成,客户端需要与这些子系统进行交互,但直接交互会导致客户端代码复杂且难以维护。比如:
- 家庭影院系统:打开投影仪、打开音响、调暗灯光、播放电影
- 电商下单系统:库存检查、价格计算、优惠券验证、支付处理、物流创建
- 计算机启动系统:CPU自检、内存检查、设备初始化、系统加载
- 微服务调用:用户服务、订单服务、支付服务、库存服务
初级程序员的写法:
java
// 客户端直接调用所有子系统
public class HomeTheaterClient {
private Projector projector;
private Amplifier amplifier;
private Lights lights;
private DVDPlayer dvdPlayer;
public void watchMovie(String movie) {
// 需要了解所有子系统的接口和调用顺序
projector.on();
projector.setInput("DVD");
amplifier.on();
amplifier.setVolume(5);
amplifier.setSource("DVD");
lights.dim(10);
dvdPlayer.on();
dvdPlayer.play(movie);
System.out.println("开始观看电影: " + movie);
}
public void endMovie() {
// 同样需要了解关闭顺序
dvdPlayer.stop();
dvdPlayer.off();
lights.on();
amplifier.off();
projector.off();
}
}
这种写法的痛点:
- ❌ 客户端复杂度高:客户端需要了解所有子系统的接口
- ❌ 紧耦合:客户端与多个子系统紧密耦合
- ❌ 难以维护:子系统变化会影响所有客户端
- ❌ 重复代码:相同的调用逻辑在多个地方重复
2. 外观模式:本质与定义
2.1 模式定义
外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
2.2 模式结构
java
// 子系统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 subsystemA;
private SubsystemB subsystemB;
private SubsystemC subsystemC;
public Facade() {
this.subsystemA = new SubsystemA();
this.subsystemB = new SubsystemB();
this.subsystemC = new SubsystemC();
}
// 简化后的高层接口
public void simplifiedOperation() {
System.out.println("外观模式简化操作开始");
subsystemA.operationA();
subsystemB.operationB();
subsystemC.operationC();
System.out.println("外观模式简化操作结束");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.simplifiedOperation(); // 只需调用一个方法
}
}
3. 深入理解
3.1 接口简化
核心思想:将复杂的子系统调用封装成简单的高层接口。
java
// 复杂的使用方式
public class ComplexClient {
public void complexOperation() {
ServiceA a = new ServiceA();
ServiceB b = new ServiceB();
ServiceC c = new ServiceC();
a.initialize();
b.setup();
c.prepare();
a.execute();
b.process();
c.run();
a.cleanup();
b.finish();
c.dispose();
}
}
// 简化的使用方式
public class SimpleClient {
public void simpleOperation() {
Facade facade = new Facade();
facade.easyOperation(); // 一个方法搞定
}
}
3.2 依赖倒置
设计原则的体现:客户端不再依赖具体的子系统,而是依赖外观接口。
java
// 不好的做法:客户端直接依赖多个子系统
public class BadClient {
private ServiceA serviceA;
private ServiceB serviceB;
private ServiceC serviceC;
// 依赖太多,耦合度高
}
// 好的做法:客户端只依赖外观
public class GoodClient {
private Facade facade;
// 只依赖一个外观,耦合度低
}
3.3 使用接口进一步解耦
通过接口定义外观,让客户端只依赖抽象外观,不依赖具体外观实现。
java
// 外观接口
public interface HomeTheaterFacade {
void watchMovie(String movie);
void endMovie();
void listenToMusic(String music);
}
// 具体外观实现
public class BasicHomeTheaterFacade implements HomeTheaterFacade {
// 实现接口方法
}
// 客户端只依赖接口
public class Client {
private HomeTheaterFacade facade;
public Client(HomeTheaterFacade facade) {
this.facade = facade;
}
}
4. 实战案例:完整的智能家居控制系统
让我们来看一个完整的例子:
java
// 子系统类 - 各种智能设备
@Slf4j
public class LightSystem {
public void on() {
log.info("灯光系统:打开所有灯光");
}
public void off() {
log.info("灯光系统:关闭所有灯光");
}
public void dim(int level) {
log.info("灯光系统:调暗灯光到 {}%", level);
}
public void setColor(String color) {
log.info("灯光系统:设置灯光颜色为 {}", color);
}
}
@Slf4j
public class AudioSystem {
public void on() {
log.info("音响系统:打开音响");
}
public void off() {
log.info("音响系统:关闭音响");
}
public void setVolume(int level) {
log.info("音响系统:设置音量为 {}", level);
}
public void setSource(String source) {
log.info("音响系统:设置音源为 {}", source);
}
public void playMusic(String music) {
log.info("音响系统:播放音乐 {}", music);
}
public void stopMusic() {
log.info("音响系统:停止播放音乐");
}
}
@Slf4j
public class VideoSystem {
public void on() {
log.info("视频系统:打开视频设备");
}
public void off() {
log.info("视频系统:关闭视频设备");
}
public void setInput(String input) {
log.info("视频系统:设置输入源为 {}", input);
}
public void playMovie(String movie) {
log.info("视频系统:播放电影 {}", movie);
}
public void stopMovie() {
log.info("视频系统:停止播放电影");
}
}
@Slf4j
public class ClimateSystem {
public void setTemperature(double temperature) {
log.info("空调系统:设置温度为 {}°C", temperature);
}
public void setMode(String mode) {
log.info("空调系统:设置模式为 {}", mode);
}
public void turnOn() {
log.info("空调系统:打开空调");
}
public void turnOff() {
log.info("空调系统:关闭空调");
}
}
@Slf4j
public class SecuritySystem {
public void arm() {
log.info("安防系统:布防");
}
public void disarm() {
log.info("安防系统:撤防");
}
public void lockDoors() {
log.info("安防系统:锁门");
}
public void unlockDoors() {
log.info("安防系统:解锁门");
}
}
@Slf4j
public class CurtainSystem {
public void open() {
log.info("窗帘系统:打开窗帘");
}
public void close() {
log.info("窗帘系统:关闭窗帘");
}
}
// 外观接口
public interface SmartHomeFacade {
// 场景模式
void enterHomeMode();
void leaveHomeMode();
void movieMode(String movie);
void partyMode(String music);
void sleepMode();
void wakeUpMode();
// 单个设备控制
void controlLights(boolean on, Integer dimLevel, String color);
void controlAudio(boolean on, Integer volume, String source);
void controlClimate(double temperature, String mode);
}
// 具体外观实现
@Slf4j
public class SmartHomeFacadeImpl implements SmartHomeFacade {
private final LightSystem lightSystem;
private final AudioSystem audioSystem;
private final VideoSystem videoSystem;
private final ClimateSystem climateSystem;
private final SecuritySystem securitySystem;
private final CurtainSystem curtainSystem;
public SmartHomeFacadeImpl() {
this.lightSystem = new LightSystem();
this.audioSystem = new AudioSystem();
this.videoSystem = new VideoSystem();
this.climateSystem = new ClimateSystem();
this.securitySystem = new SecuritySystem();
this.curtainSystem = new CurtainSystem();
}
@Override
public void enterHomeMode() {
log.info("=== 进入回家模式 ===");
securitySystem.disarm();
securitySystem.unlockDoors();
lightSystem.on();
climateSystem.turnOn();
climateSystem.setTemperature(22.0);
climateSystem.setMode("舒适");
audioSystem.on();
audioSystem.setVolume(20);
audioSystem.playMusic("欢迎回家音乐");
log.info("=== 回家模式设置完成 ===\n");
}
@Override
public void leaveHomeMode() {
log.info("=== 进入离家模式 ===");
audioSystem.stopMusic();
audioSystem.off();
lightSystem.off();
climateSystem.turnOff();
curtainSystem.close();
securitySystem.lockDoors();
securitySystem.arm();
log.info("=== 离家模式设置完成 ===\n");
}
@Override
public void movieMode(String movie) {
log.info("=== 进入观影模式 ===");
curtainSystem.close();
lightSystem.dim(10);
lightSystem.setColor("暖黄");
climateSystem.setTemperature(24.0);
climateSystem.setMode("静音");
audioSystem.on();
audioSystem.setVolume(30);
audioSystem.setSource("电影");
videoSystem.on();
videoSystem.setInput("HDMI");
videoSystem.playMovie(movie);
log.info("=== 观影模式设置完成,开始播放: {} ===\n", movie);
}
@Override
public void partyMode(String music) {
log.info("=== 进入派对模式 ===");
curtainSystem.open();
lightSystem.on();
lightSystem.setColor("多彩");
climateSystem.setTemperature(20.0);
climateSystem.setMode("通风");
audioSystem.on();
audioSystem.setVolume(60);
audioSystem.setSource("蓝牙");
audioSystem.playMusic(music);
log.info("=== 派对模式设置完成,播放音乐: {} ===\n", music);
}
@Override
public void sleepMode() {
log.info("=== 进入睡眠模式 ===");
audioSystem.stopMusic();
audioSystem.off();
videoSystem.stopMovie();
videoSystem.off();
lightSystem.dim(5);
lightSystem.setColor("暖黄");
climateSystem.setTemperature(20.0);
climateSystem.setMode("睡眠");
curtainSystem.close();
securitySystem.arm();
log.info("=== 睡眠模式设置完成 ===\n");
}
@Override
public void wakeUpMode() {
log.info("=== 进入唤醒模式 ===");
curtainSystem.open();
lightSystem.on();
lightSystem.setColor("自然白");
climateSystem.setTemperature(22.0);
climateSystem.setMode("舒适");
audioSystem.on();
audioSystem.setVolume(15);
audioSystem.playMusic("清晨音乐");
securitySystem.disarm();
log.info("=== 唤醒模式设置完成 ===\n");
}
@Override
public void controlLights(boolean on, Integer dimLevel, String color) {
log.info("=== 灯光控制 ===");
if (on) {
lightSystem.on();
if (dimLevel != null) {
lightSystem.dim(dimLevel);
}
if (color != null) {
lightSystem.setColor(color);
}
} else {
lightSystem.off();
}
log.info("=== 灯光控制完成 ===\n");
}
@Override
public void controlAudio(boolean on, Integer volume, String source) {
log.info("=== 音响控制 ===");
if (on) {
audioSystem.on();
if (volume != null) {
audioSystem.setVolume(volume);
}
if (source != null) {
audioSystem.setSource(source);
}
} else {
audioSystem.off();
}
log.info("=== 音响控制完成 ===\n");
}
@Override
public void controlClimate(double temperature, String mode) {
log.info("=== 空调控制 ===");
climateSystem.turnOn();
climateSystem.setTemperature(temperature);
if (mode != null) {
climateSystem.setMode(mode);
}
log.info("=== 空调控制完成 ===\n");
}
}
// 客户端代码
@Slf4j
public class SmartHomeClient {
private SmartHomeFacade smartHome;
public SmartHomeClient(SmartHomeFacade smartHome) {
this.smartHome = smartHome;
}
public void simulateDailyRoutine() {
log.info("开始模拟智能家居日常场景\n");
// 早上起床
log.info("7:00 AM - 起床时间");
smartHome.wakeUpMode();
// 出门上班
log.info("8:30 AM - 出门上班");
smartHome.leaveHomeMode();
// 下班回家
log.info("6:00 PM - 下班回家");
smartHome.enterHomeMode();
// 晚上看电影
log.info("8:00 PM - 家庭影院时间");
smartHome.movieMode("阿凡达");
// 准备睡觉
log.info("11:00 PM - 睡觉时间");
smartHome.sleepMode();
log.info("日常场景模拟结束");
}
public void controlIndividualDevices() {
log.info("开始单个设备控制演示\n");
// 单独控制灯光
smartHome.controlLights(true, 80, "自然白");
// 单独控制音响
smartHome.controlAudio(true, 25, "FM收音机");
// 单独控制空调
smartHome.controlClimate(23.5, "自动");
}
}
// 使用示例
public class FacadePatternDemo {
public static void main(String[] args) {
// 创建外观
SmartHomeFacade smartHome = new SmartHomeFacadeImpl();
// 创建客户端
SmartHomeClient client = new SmartHomeClient(smartHome);
// 演示场景模式
System.out.println("====== 场景模式演示 ======");
client.simulateDailyRoutine();
// 演示单个设备控制
System.out.println("\n====== 单个设备控制演示 ======");
client.controlIndividualDevices();
// 演示直接使用外观
System.out.println("\n====== 直接外观调用演示 ======");
smartHome.partyMode("派对音乐");
}
}
5. Spring Boot中的实现
在Spring Boot中,我们可以利用依赖注入让外观模式更加优雅:
java
// 微服务客户端(模拟)
@Component
@Slf4j
public class UserServiceClient {
public User getUserById(String userId) {
log.info("用户服务:获取用户信息,用户ID: {}", userId);
return new User(userId, "张三", "zhangsan@example.com");
}
public boolean validateUser(String userId) {
log.info("用户服务:验证用户,用户ID: {}", userId);
return true;
}
}
@Component
@Slf4j
public class InventoryServiceClient {
public boolean checkInventory(String productId, int quantity) {
log.info("库存服务:检查库存,产品ID: {},数量: {}", productId, quantity);
return quantity <= 100; // 模拟库存检查
}
public void reduceInventory(String productId, int quantity) {
log.info("库存服务:减少库存,产品ID: {},数量: {}", productId, quantity);
}
}
@Component
@Slf4j
public class PricingServiceClient {
public BigDecimal calculatePrice(String productId, int quantity, String couponCode) {
log.info("价格服务:计算价格,产品ID: {},数量: {},优惠券: {}", productId, quantity, couponCode);
BigDecimal basePrice = new BigDecimal("99.99");
BigDecimal total = basePrice.multiply(BigDecimal.valueOf(quantity));
// 模拟优惠券逻辑
if ("DISCOUNT10".equals(couponCode)) {
total = total.multiply(new BigDecimal("0.9"));
}
return total;
}
public boolean validateCoupon(String couponCode) {
log.info("价格服务:验证优惠券: {}", couponCode);
return couponCode == null || "DISCOUNT10".equals(couponCode);
}
}
@Component
@Slf4j
public class PaymentServiceClient {
public PaymentResult processPayment(String orderId, BigDecimal amount, PaymentMethod method) {
log.info("支付服务:处理支付,订单ID: {},金额: {},支付方式: {}", orderId, amount, method);
// 模拟支付处理
boolean success = Math.random() > 0.1; // 90%成功率
if (success) {
return new PaymentResult(true, "支付成功", UUID.randomUUID().toString());
} else {
return new PaymentResult(false, "支付失败", null);
}
}
}
@Component
@Slf4j
public class ShippingServiceClient {
public ShippingInfo createShipping(String orderId, String address) {
log.info("物流服务:创建物流,订单ID: {},地址: {}", orderId, address);
return new ShippingInfo(UUID.randomUUID().toString(), "顺丰快递", "已揽收");
}
}
// 订单外观服务
@Service
@Slf4j
public class OrderFacadeService {
private final UserServiceClient userService;
private final InventoryServiceClient inventoryService;
private final PricingServiceClient pricingService;
private final PaymentServiceClient paymentService;
private final ShippingServiceClient shippingService;
public OrderFacadeService(UserServiceClient userService,
InventoryServiceClient inventoryService,
PricingServiceClient pricingService,
PaymentServiceClient paymentService,
ShippingServiceClient shippingService) {
this.userService = userService;
this.inventoryService = inventoryService;
this.pricingService = pricingService;
this.paymentService = paymentService;
this.shippingService = shippingService;
}
@Transactional
public OrderResult placeOrder(OrderRequest request) {
log.info("开始处理订单请求: {}", request);
try {
// 1. 验证用户
if (!userService.validateUser(request.getUserId())) {
return OrderResult.failure("用户验证失败");
}
// 2. 验证优惠券
if (!pricingService.validateCoupon(request.getCouponCode())) {
return OrderResult.failure("优惠券无效");
}
// 3. 检查库存
if (!inventoryService.checkInventory(request.getProductId(), request.getQuantity())) {
return OrderResult.failure("库存不足");
}
// 4. 计算价格
BigDecimal totalAmount = pricingService.calculatePrice(
request.getProductId(), request.getQuantity(), request.getCouponCode());
// 5. 处理支付
PaymentResult paymentResult = paymentService.processPayment(
request.getOrderId(), totalAmount, request.getPaymentMethod());
if (!paymentResult.isSuccess()) {
return OrderResult.failure("支付失败: " + paymentResult.getMessage());
}
// 6. 减少库存
inventoryService.reduceInventory(request.getProductId(), request.getQuantity());
// 7. 创建物流
ShippingInfo shippingInfo = shippingService.createShipping(
request.getOrderId(), request.getShippingAddress());
// 8. 获取用户信息
User user = userService.getUserById(request.getUserId());
log.info("订单处理成功: {}", request.getOrderId());
return OrderResult.success(
request.getOrderId(),
totalAmount,
paymentResult.getTransactionId(),
shippingInfo.getTrackingNumber(),
user
);
} catch (Exception e) {
log.error("订单处理失败: {}", request.getOrderId(), e);
return OrderResult.failure("系统错误: " + e.getMessage());
}
}
public OrderStatus checkOrderStatus(String orderId) {
log.info("检查订单状态: {}", orderId);
// 模拟状态检查
// 在实际系统中,这里会查询各个服务的状态
return new OrderStatus(orderId, "已完成", LocalDateTime.now());
}
}
// DTO类
@Data
@AllArgsConstructor
class User {
private String userId;
private String name;
private String email;
}
@Data
@AllArgsConstructor
class PaymentResult {
private boolean success;
private String message;
private String transactionId;
}
@Data
@AllArgsConstructor
class ShippingInfo {
private String trackingNumber;
private String shippingCompany;
private String status;
}
@Data
class OrderRequest {
private String orderId;
private String userId;
private String productId;
private int quantity;
private String couponCode;
private PaymentMethod paymentMethod;
private String shippingAddress;
public OrderRequest() {
this.orderId = "ORDER_" + System.currentTimeMillis();
}
}
enum PaymentMethod {
ALIPAY, WECHAT, CREDIT_CARD
}
@Data
@AllArgsConstructor
class OrderResult {
private boolean success;
private String orderId;
private BigDecimal totalAmount;
private String transactionId;
private String trackingNumber;
private User user;
private String message;
public static OrderResult success(String orderId, BigDecimal totalAmount,
String transactionId, String trackingNumber, User user) {
return new OrderResult(true, orderId, totalAmount, transactionId, trackingNumber, user, "订单创建成功");
}
public static OrderResult failure(String message) {
return new OrderResult(false, null, null, null, null, null, message);
}
}
@Data
@AllArgsConstructor
class OrderStatus {
private String orderId;
private String status;
private LocalDateTime updateTime;
}
// REST控制器
@RestController
@RequestMapping("/api/orders")
@Slf4j
public class OrderController {
private final OrderFacadeService orderFacadeService;
public OrderController(OrderFacadeService orderFacadeService) {
this.orderFacadeService = orderFacadeService;
}
@PostMapping("/place")
public ResponseEntity<OrderResult> placeOrder(@RequestBody OrderRequest request) {
log.info("收到下单请求: {}", request);
OrderResult result = orderFacadeService.placeOrder(request);
if (result.isSuccess()) {
return ResponseEntity.ok(result);
} else {
return ResponseEntity.badRequest().body(result);
}
}
@GetMapping("/{orderId}/status")
public ResponseEntity<OrderStatus> getOrderStatus(@PathVariable String orderId) {
OrderStatus status = orderFacadeService.checkOrderStatus(orderId);
return ResponseEntity.ok(status);
}
}
// 配置类
@Configuration
@Slf4j
public class AppConfig {
@Bean
@Order(1)
public CommandLineRunner demo(OrderFacadeService orderFacadeService) {
return args -> {
log.info("开始外观模式演示...");
// 模拟订单请求
OrderRequest request = new OrderRequest();
request.setUserId("USER_001");
request.setProductId("PRODUCT_001");
request.setQuantity(2);
request.setCouponCode("DISCOUNT10");
request.setPaymentMethod(PaymentMethod.ALIPAY);
request.setShippingAddress("北京市朝阳区xxx街道");
OrderResult result = orderFacadeService.placeOrder(request);
if (result.isSuccess()) {
log.info("订单创建成功: {}", result.getOrderId());
log.info("订单金额: {}", result.getTotalAmount());
log.info("交易ID: {}", result.getTransactionId());
log.info("物流单号: {}", result.getTrackingNumber());
} else {
log.error("订单创建失败: {}", result.getMessage());
}
};
}
}
6. 外观模式的变体与进阶用法
6.1 多层外观模式
对于特别复杂的系统,可以设计多层外观:
java
// 底层外观
@Service
@Slf4j
public class PaymentFacadeService {
private final PaymentGateway paymentGateway;
private final FraudDetectionService fraudDetection;
private final NotificationService notificationService;
public PaymentResult processPayment(PaymentRequest request) {
// 反欺诈检查
if (!fraudDetection.check(request)) {
return PaymentResult.failure("反欺诈检查失败");
}
// 支付处理
PaymentResult result = paymentGateway.process(request);
// 发送通知
if (result.isSuccess()) {
notificationService.sendPaymentSuccess(request, result);
}
return result;
}
}
// 高层外观
@Service
@Slf4j
public class OrderManagementFacadeService {
private final OrderFacadeService orderFacade;
private final PaymentFacadeService paymentFacade;
private final InventoryFacadeService inventoryFacade;
public CompleteOrderResult processCompleteOrder(CompleteOrderRequest request) {
// 使用各个底层外观完成复杂业务流程
OrderResult orderResult = orderFacade.placeOrder(request.getOrderRequest());
if (!orderResult.isSuccess()) {
return CompleteOrderResult.failure(orderResult.getMessage());
}
// 其他业务逻辑...
return CompleteOrderResult.success(orderResult);
}
}
6.2 可配置的外观模式
通过配置决定使用哪些子系统:
java
@Configuration
@Slf4j
public class FacadeConfiguration {
@Bean
@ConditionalOnProperty(name = "features.advanced-audio", havingValue = "true")
public AudioSystem advancedAudioSystem() {
return new AdvancedAudioSystem();
}
@Bean
@ConditionalOnProperty(name = "features.advanced-audio", havingValue = "false", matchIfMissing = true)
public AudioSystem basicAudioSystem() {
return new BasicAudioSystem();
}
@Bean
public SmartHomeFacade smartHomeFacade(AudioSystem audioSystem,
LightSystem lightSystem,
@Value("${features.mode:basic}") String mode) {
if ("advanced".equals(mode)) {
return new AdvancedSmartHomeFacade(audioSystem, lightSystem);
} else {
return new BasicSmartHomeFacade(audioSystem, lightSystem);
}
}
}
7. 外观模式 vs 其他模式
7.1 外观模式 vs 中介者模式
- 外观模式:简化客户端与子系统的交互,单向通信
- 中介者模式:协调多个对象之间的交互,双向通信
7.2 外观模式 vs 适配器模式
- 外观模式:简化接口,让现有系统更容易使用
- 适配器模式:转换接口,让不兼容的接口能够一起工作
7.3 外观模式 vs 门面模式
- 外观模式:其实就是门面模式,只是翻译不同
- 两者是同一个模式的不同称呼
8. 总结与思考
8.1 外观模式的优点
- 简化客户端:客户端只需要与外观对象交互,无需了解复杂子系统
- 松耦合:客户端与子系统解耦,子系统变化不影响客户端
- 易于使用:提供简单一致的高层接口
- 层次化:可以定义多层外观,管理不同层次的复杂度
8.2 外观模式的缺点
- 不够灵活:如果客户端需要访问子系统的特定功能,可能受到限制
- 增加复杂度:引入了新的抽象层
- 单点故障:外观对象成为系统的单点故障
8.3 深入思考
外观模式的本质是**"复杂度的封装"**。它通过在复杂系统前设置一个简单的接口,隐藏系统的复杂性,让客户端能够以最简单的方式使用系统功能。
设计之美的思考:
"外观模式就像现实世界中的客户服务中心。当你遇到问题时,不需要知道公司内部有哪些部门、每个部门的职责是什么,只需要拨打一个统一的客服电话,客服人员会帮你协调所有相关部门解决问题。这种'一站式服务'的理念,极大地提升了用户体验。"
从源码的角度看,外观模式在Java中有着广泛应用:
- Spring Framework 的
JdbcTemplate封装了复杂的JDBC操作 - SLF4J 日志门面封装了各种日志实现
- Java AWT 的
Graphics类封装了复杂的图形绘制操作 - Tomcat 的
HttpServletRequest和HttpServletResponse封装了HTTP协议细节
何时使用外观模式:
- 要为复杂的子系统提供简单接口时
- 客户端与多个子系统之间存在很多依赖关系时
- 需要层次化子系统时,可以使用外观模式定义每层的入口点
- 需要解耦客户端与子系统时
使用场景:
- 智能家居控制系统
- 微服务架构中的API网关
- 复杂库或框架的简单入口
- 遗留系统的现代化包装
- 多层架构中的层间通信
版权声明:本文为CSDN博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。