小易说IT 小易说IT

Java 外观模式(Facade)示例代码

外观模式:为子系统的一组接口提供一个统一高层入口,隐藏子系统内部复杂细节,客户端只需要调用外观类,不用直接和多个子系统类交互,降低耦合。

角色:

  1. 子系统类:完成各自独立功能,对外提供方法,不知道外观类存在

  2. 外观 (Facade) 类:持有各个子系统对象,封装组合调用,对外提供简单接口

  3. 客户端:只依赖外观类,不直接访问子系统

场景举例

家庭影院:包含灯光、投影仪、音响、DVD 播放器。 看电影时需要:调暗灯光 → 开投影仪 → 开音响 → 播放 DVD; 结束:停止 DVD → 关音响 → 关投影仪 → 开灯。 客户端不用依次调用每一个设备,交给HomeTheaterFacade统一操作。

// ----------------------子系统1:灯光----------------------
class TheaterLight {
    public void dim(int level) {
        System.out.println("灯光调暗,亮度:" + level);
    }
    public void on() {
        System.out.println("灯光打开");
    }
}

// ----------------------子系统2:投影仪----------------------
class Projector {
    public void on() {
        System.out.println("投影仪开机");
    }
    public void wideScreenMode() {
        System.out.println("投影仪切换宽屏模式");
    }
    public void off() {
        System.out.println("投影仪关机");
    }
}

// ----------------------子系统3:音响----------------------
class Stereo {
    public void on() {
        System.out.println("音响开机");
    }
    public void setVolume(int vol) {
        System.out.println("音响音量设置:" + vol);
    }
    public void off() {
        System.out.println("相机关闭");
    }
}

// ----------------------子系统4:DVD播放器----------------------
class DvdPlayer {
    public void play(String movie) {
        System.out.println("DVD正在播放:" + movie);
    }
    public void stop() {
        System.out.println("DVD停止播放");
    }
    public void off() {
        System.out.println("DVD播放器关机");
    }
}

// ----------------------外观Facade 核心类----------------------
/**
 * 家庭影院外观类,封装整套复杂操作
 */
public class HomeTheaterFacade {
    // 持有所有子系统
    private final TheaterLight light;
    private final Projector projector;
    private final Stereo stereo;
    private final DvdPlayer dvdPlayer;

    // 构造注入所有子系统
    public HomeTheaterFacade(TheaterLight light, Projector projector, Stereo stereo, DvdPlayer dvdPlayer) {
        this.light = light;
        this.projector = projector;
        this.stereo = stereo;
        this.dvdPlayer = dvdPlayer;
    }

    /**
     * 对外简单接口:一键看电影
     */
    public void watchMovie(String movieName) {
        System.out.println("=====准备看电影=====");
        light.dim(10);
        projector.on();
        projector.wideScreenMode();
        stereo.on();
        stereo.setVolume(60);
        dvdPlayer.play(movieName);
    }

    /**
     * 对外简单接口:一键结束观影
     */
    public void endMovie() {
        System.out.println("\n=====结束电影,关闭设备=====");
        dvdPlayer.stop();
        dvdPlayer.off();
        stereo.off();
        projector.off();
        light.on();
    }
}

// ----------------------客户端测试----------------------
class Client {
    public static void main(String[] args) {
        // 实例化所有子系统
        TheaterLight light = new TheaterLight();
        Projector projector = new Projector();
        Stereo stereo = new Stereo();
        DvdPlayer dvd = new DvdPlayer();

        // 创建外观对象
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(light, projector, stereo, dvd);

        // 客户端只调用外观简单方法,不需要关心内部设备顺序
        homeTheater.watchMovie("星际穿越");
        homeTheater.endMovie();
    }
}

输出结果

=====准备看电影=====
灯光调暗,亮度:10
投影仪开机
投影仪切换宽屏模式
音响开机
音响音量设置:60
DVD正在播放:星际穿越

=====结束电影,关闭设备=====
DVD停止播放
DVD播放器关机
相机关闭
投影仪关机
灯光打开

外观模式要点

  1. 不修改子系统代码,只做封装组合,子系统可以继续被客户端直接调用,外观不是屏蔽子系统,只是提供简化入口;

  2. 外观类可以有多个,一个子系统可以被多个 Facade 使用;

  3. 符合迪米特法则,客户端只和 Facade 交互,减少大量子系统依赖;

  4. 典型业务场景:网关封装多方 SDK、支付聚合门面、复杂底层工具封装对外简单 API。

UML 简要说明

客户端 → HomeTheaterFacade(外观)
                ↓ 组合持有
        ┌───┬───┴───┬───┐
      灯光 投影仪   音响  DVD播放器(各个子系统)

本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://yijunzhao.cc/archives/java-facade-pattern-example-code

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/