23种设计模式之【外观模式】-核心原理与 Java实践
外观模式(Facade Pattern)
外观模式是 23 种设计模式中的一种结构型模式,其核心思想是为复杂系统中的一组接口提供一个统一的高层接口,使子系统更易于使用。这种模式通过引入一个 “外观类”,封装子系统的复杂性,为客户端提供简单直观的访问入口,从而降低客户端与子系统之间的耦合度。
核心原理
外观角色(Facade):
提供一个统一的接口,封装子系统的复杂交互逻辑
客户端通过外观类访问子系统,无需直接与子系统交互
子系统角色(Subsystem):
由多个相关联的类组成,实现子系统的具体功能
对子系统而言,外观类只是另一个客户端,不影响子系统内部结构
客户端(Client):
通过外观类与子系统交互,无需了解子系统的内部实现
简化了与复杂系统的交互过程
外观模式的核心是 “封装复杂性,提供简化接口”,遵循 “最少知识原则”(迪米特原则),减少客户端需要了解的类和方法数量。
Java 实践示例
以 “家庭影院系统” 为例实现外观模式:
家庭影院包含多个设备(投影仪、音响、播放器、灯光等)
观看电影需要协调多个设备的操作(开投影仪、开音响、关灯光等)
外观类封装这些复杂操作,提供 “一键观影” 的简化接口
package com.example.demo;
public class FacadePattern {
public static void main(String[] args) {
// 创建子系统组件
Projector projector = new Projector();
SoundSystem soundSystem = new SoundSystem();
Player player = new Player();
Light light = new Light();
// 创建外观类
HomeTheaterFacade theaterFacade = new HomeTheaterFacade(
projector, soundSystem, player, light
);
System.out.println("=== 准备观看电影 ===");
theaterFacade.watchMovie("星际穿越");
System.out.println("\n=== 电影结束 ===");
theaterFacade.endMovie();
}
// 子系统:投影仪
public static class Projector {
public void on() {
System.out.println("投影仪已开启");
}
public void off() {
System.out.println("投影仪已关闭");
}
public void setInput(String source) {
System.out.println("投影仪输入源设置为:" + source);
}
public void zoomIn() {
System.out.println("投影仪画面放大");
}
}
// 子系统:音响系统
public static class SoundSystem {
public void on() {
System.out.println("音响系统已开启");
}
public void off() {
System.out.println("音响系统已关闭");
}
public void setVolume(int level) {
System.out.println("音响音量设置为:" + level);
}
}
// 子系统:播放器
public static class Player {
public void on() {
System.out.println("播放器已开启");
}
public void off() {
System.out.println("播放器已关闭");
}
public void play(String movie) {
System.out.println("正在播放电影:" + movie);
}
public void stop() {
System.out.println("电影播放已停止");
}
}
// 子系统:灯光
public static class Light {
public void dim(int level) {
System.out.println("灯光调暗至:" + level + "%");
}
public void on() {
System.out.println("灯光已打开");
}
}
// 外观类:家庭影院外观
public static class HomeTheaterFacade {
// 持有子系统组件的引用
private Projector projector;
private SoundSystem soundSystem;
private Player player;
private Light light;
// 通过构造函数注入子系统组件
public HomeTheaterFacade(Projector projector, SoundSystem soundSystem,
Player player, Light light) {
this.projector = projector;
this.soundSystem = soundSystem;
this.player = player;
this.light = light;
}
// 封装观看电影的复杂流程
public void watchMovie(String movie) {
System.out.println("准备观看电影...");
light.dim(20); // 调暗灯光
projector.on(); // 打开投影仪
projector.setInput("播放器"); // 设置输入源
projector.zoomIn(); // 放大画面
soundSystem.on(); // 打开音响
soundSystem.setVolume(8); // 设置音量
player.on(); // 打开播放器
player.play(movie); // 播放电影
}
// 封装结束电影的复杂流程
public void endMovie() {
System.out.println("结束电影...");
light.on(); // 打开灯光
projector.off(); // 关闭投影仪
soundSystem.off(); // 关闭音响
player.stop(); // 停止播放
player.off(); // 关闭播放器
}
}
//=== 准备观看电影 ===
//准备观看电影...
//灯光调暗至:20%
//投影仪已开启
//投影仪输入源设置为:播放器
//投影仪画面放大
//音响系统已开启
//音响音量设置为:8
//播放器已开启
//正在播放电影:星际穿越
//
//=== 电影结束 ===
//结束电影...
//灯光已打开
//投影仪已关闭
//音响系统已关闭
//电影播放已停止
//播放器已关闭
}
外观模式的特点
优点:
简化接口:为复杂子系统提供简单统一的访问接口,降低使用难度
解耦客户端与子系统:客户端无需了解子系统内部结构,减少耦合
提高灵活性:子系统内部变化时,只需调整外观类,不影响客户端
符合迪米特原则:客户端只需与外观类交互,减少与其他类的通信
缺点:
外观类可能成为 “上帝对象”,承担过多职责
新增子系统功能时,可能需要修改外观类,违反开闭原则
与适配器模式的区别:
外观模式:为复杂系统提供简化接口,不改变原有接口
适配器模式:将一个接口转换为另一个接口,解决接口不兼容问题
外观模式的应用场景
复杂系统简化:
当系统包含多个子模块,且模块间交互复杂时
例如:电商平台的下单流程(涉及库存、支付、物流等子系统)
框架封装:
框架为开发者提供简化接口,隐藏内部实现细节
例如:Spring 的JdbcTemplate封装了复杂的 JDBC 操作
例如:MyBatis 的SqlSession封装了数据库访问的复杂逻辑
遗留系统集成:
为老旧系统提供新的外观接口,便于与新系统集成
避免直接修改遗留系统代码,降低风险
分层架构中的层间交互:
在分层架构中,每层可为上层提供外观接口
例如:服务层为控制层提供外观接口,封装多个 DAO 的交互
外观模式是 “封装复杂性” 的典型实现,在框架设计和系统集成中应用广泛。它通过提供简洁接口,降低了系统的使用门槛,同时隔离了客户端与子系统的直接依赖,提高了系统的可维护性。
更多推荐
所有评论(0)