自学教程 学编程从这里开始

外观模式

《外观模式》|设计模式系列第11篇

系列:结构型模式 · 外观模式(Facade Pattern)
关键词:门面、统一入口、简化调用、封装子系统、降低耦合

一、什么是外观模式

外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

属于结构型设计模式。

简单理解:
外观就像酒店前台。酒店内部包含保洁、维修、餐饮等多个独立部门(子系统),客人不需要分别去找各个部门沟通;只需要找前台(外观),前台内部去协调各个子系统。外观不修改子系统原有代码,只是封装复杂调用流程,对外暴露简单入口。

核心意图
封装多个子系统的复杂调用逻辑,对外提供简洁统一高层接口,降低客户端使用复杂度。

适用场景

  1. 复杂子系统,客户端需要多次调用多个类才能完成业务
  2. 希望隔离客户端与子系统,减少依赖
  3. 分层架构,每一层对外提供 Facade,层与层之间通过外观通信
  4. 新旧系统整合,提供统一接入入口

⚠️ 缺点预警:外观类职责过重;外观类修改会影响全部客户端;不要过度包装。

二、UML结构图

角色划分:

  1. Facade(外观):高层接口,内部调用多个子系统模块,封装调用流程
  2. SubSystem(子系统):多个独立模块,实现底层能力,不知道 Facade 的存在
  3. Client(客户端):只依赖 Facade,不直接访问子系统

三、Java 完整示例

场景:影院家庭影院系统,包含 Light、Projector、Player。观影需要依次执行开灯、开投影、开播放器;观影结束依次关闭设备。
代码全部使用英文。

1. SubSystem 子系统

// Light
public class Light {
    public void dim() {
        System.out.println("Light dim to low brightness");
    }
    public void bright() {
        System.out.println("Light turn to bright");
    }
}

// Projector
public class Projector {
    public void on() {
        System.out.println("Projector turn on");
    }
    public void off() {
        System.out.println("Projector turn off");
    }
}

// Player
public class Player {
    public void play() {
        System.out.println("Media player start playing");
    }
    public void stop() {
        System.out.println("Media player stop");
    }
}

2. Facade 外观类

public class HomeTheaterFacade {
    private Light light;
    private Projector projector;
    private Player player;

    public HomeTheaterFacade(Light light, Projector projector, Player player) {
        this.light = light;
        this.projector = projector;
        this.player = player;
    }

    public void watchMovie() {
        System.out.println("=== Prepare to watch movie ===");
        light.dim();
        projector.on();
        player.play();
    }

    public void endMovie() {
        System.out.println("=== End movie ===");
        player.stop();
        projector.off();
        light.bright();
    }
}

3. Client 客户端

public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        Projector projector = new Projector();
        Player player = new Player();

        HomeTheaterFacade theater = new HomeTheaterFacade(light, projector, player);
        theater.watchMovie();
        theater.endMovie();
    }
}

客户端只需要调用 watchMovie() 和 endMovie(),不需要关心内部多个设备调用顺序。子系统类保持不变,依然可以被其他代码单独调用。

四、外观模式 vs 适配器模式

模式目标核心
Facade简化多个子系统调用,提供新的高层接口整合多个子系统,简化使用
Adapter转换已有接口,兼容已有类包装单个对象,转换接口

五、优缺点总结

✅ 优点

  1. 简化客户端调用,减少客户端依赖
  2. 解耦客户端与子系统,子系统内部修改不影响上层客户端
  3. 更好的分层管控,提供统一访问入口

❌ 缺点

  1. 外观类容易职责膨胀,违背单一职责
  2. 新增子系统时,可能需要修改外观类,违反开闭原则
  3. 如果设计不当,容易变成万能类

六、框架源码应用

  • Spring JdbcTemplate:封装JDBC底层 Connection、Statement、ResultSet 等一系列子系统操作
  • Tomcat RequestFacade
  • MyBatis SqlSession 作为门面,封装底层Executor、StatementHandler等组件

七、小结

外观模式核心:为一组子系统提供高层统一入口,简化客户端调用,不改变子系统原有接口。
外观只是简化调用,不会限制客户端直接访问底层子系统。分层架构中非常常用。

标签:

0 条笔记