跳转至

外观模式

分类:结构型模式。

类结构

classDiagram
    direction TB
    class Client
    class Facade {
        +operation()
    }
    class SubsystemA {
        +operationA()
    }
    class SubsystemB {
        +operationB()
    }
    Client ..> Facade : 使用
    Facade --> SubsystemA : 委托
    Facade --> SubsystemB : 委托

角色定义

角色 定义
Client(客户端) 通过门面完成常用任务,减少对多个子系统接口的直接依赖。
Facade(门面) 提供统一的高层入口,持有并协调子系统对象,将请求委托给相应子系统。
SubsystemA(子系统 A) 实现一部分实际业务功能,接受门面的委托,无需感知门面。
SubsystemB(子系统 B) 实现另一部分实际业务功能,与其他子系统协作完成门面组织的任务,无需感知门面。

Head First 示例:一键开始家庭影院观影

《Head First 设计模式》第 7 章的家庭影院包含功放、播放器、投影机、屏幕、灯光和爆米花机。开始观影需要按顺序操作多台设备,结束时又要逐项恢复。作者 2020 年第二版配套代码 facade/hometheater 用 HomeTheaterFacade.watchMovie() 与 endMovie() 封装这两组操作;本版本的播放设备具体类名是 StreamingPlayer。

外观对象通过构造器接收设备引用,由它组织常用流程。各设备仍保留自己的方法,也不需要依赖外观。示例入口负责创建和连接设备,观影时则只需调用外观的两个高层方法。

具体类名 对应角色 职责
HomeTheaterFacade 外观 持有设备引用,按顺序执行观影准备和结束操作。
Amplifier 功放子系统 选择播放器,设置环绕声和音量,控制功放开关。
StreamingPlayer 播放子系统 保存影片信息,提供开关机、播放和停止方法。
Projector 投影子系统 持有播放器引用,提供开关机和宽屏设置。
Screen 屏幕子系统 通过 down() 和 up() 放下或收起屏幕。
TheaterLights 灯光子系统 通过 dim() 调暗灯光,通过 on() 恢复照明。
PopcornPopper 爆米花子系统 提供开关和制作爆米花的方法。
HomeTheaterTestDrive 客户端与组装入口 创建设备和外观,调用 watchMovie()、endMovie()。

示例 UML

classDiagram
    direction TB
    class HomeTheaterFacade {
        +watchMovie(String movie)
        +endMovie()
    }
    class Amplifier {
        +on()
        +off()
        +setStreamingPlayer(StreamingPlayer player)
        +setSurroundSound()
        +setVolume(int level)
    }
    class StreamingPlayer {
        +on()
        +off()
        +play(String movie)
        +stop()
    }
    class Projector {
        +on()
        +off()
        +wideScreenMode()
    }
    class Screen {
        +down()
        +up()
    }
    class TheaterLights {
        +dim(int level)
        +on()
    }
    class PopcornPopper {
        +on()
        +pop()
        +off()
    }
    class HomeTheaterTestDrive {
        +main(String[] args)$
    }
    HomeTheaterTestDrive ..> HomeTheaterFacade : 组装并调用
    HomeTheaterFacade --> Amplifier : amp
    HomeTheaterFacade --> StreamingPlayer : player
    HomeTheaterFacade --> Projector : projector
    HomeTheaterFacade --> Screen : screen
    HomeTheaterFacade --> TheaterLights : lights
    HomeTheaterFacade --> PopcornPopper : popper
    Amplifier --> StreamingPlayer : player
    StreamingPlayer --> Amplifier : amplifier
    Projector --> StreamingPlayer : player

图中只保留观影流程,省略收音机 Tuner、未参与这段流程的 CdPlayer,以及设备描述、构造器和其他播放功能。关联线上的名称来自实际字段;这些设备类都是普通具体类,没有额外的子系统接口或共同父类。

协作过程

  1. HomeTheaterTestDrive 创建各设备,将播放器传入投影机构造器,并把观影所需对象传给 HomeTheaterFacade。
  2. 调用 watchMovie(String movie) 后,外观先开启爆米花机并制作爆米花,再把灯光调到 10、放下屏幕、开启投影机并设置宽屏。
  3. 外观开启功放,调用 setStreamingPlayer(player) 选择播放来源,开启环绕声并将音量设为 5,最后开启播放器并调用 play(movie)。
  4. 调用 endMovie() 后,外观依次关闭爆米花机、恢复灯光、收起屏幕、关闭投影机和功放,最后停止并关闭播放器。

固定版本源码:

评论