Skip to content

外观

更新: 6/28/2025 字数: 0 字 时长: 0 分钟

定义

外观模式 (Facade Pattern) 为复杂的子系统提供一个统一的简单接口,隐藏系统内部复杂性,降低客户端与子系统的耦合度。外观模式通过定义高层接口简化系统使用,是迪米特法则的典型应用。

角色

  • 外观 (Facade):提供统一的高级接口
  • 子系统类 (Subsystem Classes):实现子系统功能的多个类
  • 客户端 (Client):通过外观与子系统交互

实现

家庭影院系统示例

java
// 子系统类:投影仪
public class Projector {
    public void on() {
        System.out.println("投影仪开启");
    }
    
    public void wideScreenMode() {
        System.out.println("投影仪设置为宽屏模式");
    }
    
    public void off() {
        System.out.println("投影仪关闭");
    }
}

// 子系统类:音响系统
public class SoundSystem {
    public void on() {
        System.out.println("音响系统开启");
    }
    
    public void setVolume(int level) {
        System.out.println("音量设置为:" + level);
    }
    
    public void off() {
        System.out.println("音响系统关闭");
    }
}

// 子系统类:蓝光播放器
public class BluRayPlayer {
    public void on() {
        System.out.println("蓝光播放器开启");
    }
    
    public void play(String movie) {
        System.out.println("开始播放电影:" + movie);
    }
    
    public void off() {
        System.out.println("蓝光播放器关闭");
    }
}

// 外观类
public class HomeTheaterFacade {
    private Projector projector;
    private SoundSystem soundSystem;
    private BluRayPlayer bluRayPlayer;
    
    public HomeTheaterFacade(Projector projector, 
                            SoundSystem soundSystem, 
                            BluRayPlayer bluRayPlayer) {
        this.projector = projector;
        this.soundSystem = soundSystem;
        this.bluRayPlayer = bluRayPlayer;
    }
    
    public void watchMovie(String movie) {
        System.out.println("准备观看电影...");
        projector.on();
        projector.wideScreenMode();
        soundSystem.on();
        soundSystem.setVolume(8);
        bluRayPlayer.on();
        bluRayPlayer.play(movie);
    }
    
    public void endMovie() {
        System.out.println("结束观看电影...");
        bluRayPlayer.off();
        soundSystem.off();
        projector.off();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        // 创建子系统组件
        Projector projector = new Projector();
        SoundSystem soundSystem = new SoundSystem();
        BluRayPlayer bluRayPlayer = new BluRayPlayer();
        
        // 创建外观
        HomeTheaterFacade homeTheater = 
            new HomeTheaterFacade(projector, soundSystem, bluRayPlayer);
        
        // 通过外观使用复杂系统
        homeTheater.watchMovie("盗梦空间");
        // ...观看电影...
        homeTheater.endMovie();
    }
}

数据库连接外观示例

java
// 外观类:简化数据库操作
public class DatabaseFacade {
    private Connection connection;
    
    public DatabaseFacade(String url, String user, String password) {
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException("数据库连接失败", e);
        }
    }
    
    public void executeUpdate(String sql) {
        try (Statement stmt = connection.createStatement()) {
            stmt.executeUpdate(sql);
        } catch (SQLException e) {
            handleException(e);
        }
    }
    
    public List<Map<String, Object>> executeQuery(String sql) {
        List<Map<String, Object>> results = new ArrayList<>();
        try (Statement stmt = connection.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            
            while (rs.next()) {
                Map<String, Object> row = new HashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = metaData.getColumnName(i);
                    row.put(columnName, rs.getObject(i));
                }
                results.add(row);
            }
        } catch (SQLException e) {
            handleException(e);
        }
        return results;
    }
    
    public void close() {
        try {
            if (connection != null && !connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            // 静默关闭
        }
    }
    
    private void handleException(SQLException e) {
        // 统一的异常处理逻辑
        throw new RuntimeException("数据库操作失败:" + e.getMessage(), e);
    }
}

优缺点

优点:

  1. 简化复杂系统使用
  2. 降低客户端与子系统的耦合度
  3. 提高子系统独立性和可移植性
  4. 符合迪米特法则(最少知识原则)

缺点:

  1. 不限制直接访问子系统(需要约定)
  2. 增加新功能可能需要修改外观
  3. 可能成为"上帝对象"(过度集中功能)

应用场景

  1. 复杂子系统需要简单入口
  2. 分层系统结构(每层提供统一接口)
  3. 遗留系统重构(包装旧接口)
  4. 第三方库简化封装
  5. 微服务网关(API Gateway)

与其他模式的关系

  • 与适配器模式:适配器转换接口,外观简化接口
  • 与中介者模式:中介者协调对象间通信,外观协调子系统间通信
  • 与单例模式:外观常实现为单例
  • 与抽象工厂模式:抽象工厂可创建子系统对象
  • 与代理模式:代理控制访问,外观简化访问

JDK 中的外观模式

  1. javax.faces.context.FacesContext(JSF)
  2. java.net.URL(封装 URLConnection 等)
  3. javax.servlet.http.HttpSession(Servlet API)
  4. java.util.logging.Logger(日志门面)
  5. SLF4J 日志门面

注意事项

  1. 合理划分子系统边界
  2. 避免外观类过度膨胀
  3. 提供子系统直接访问通道(高级用户)
  4. 考虑为不同客户端提供不同外观
  5. 注意线程安全问题(共享子系统状态)

贡献者

The avatar of contributor named as AKAcxp AKAcxp

页面历史