外观模式
简介
定义: 提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。
使用场景:
复杂系统的简化接口
分层架构的各层入口
第三方库的封装
微服务网关
实现要点:
封装多个子系统
提供简化的统一接口
最少知识原则
UML
代码示例
几个子系统
public class Amplifier {
private String description;
private int volume;
public Amplifier(String description) {
this.description = description;
this.volume = 5;
}
public void on() {
System.out.println("🔊 " + description + " 功放打开");
}
public void off() {
System.out.println("🔇 " + description + " 功放关闭");
}
public void setVolume(int level) {
this.volume = level;
System.out.println("🔊 " + description + " 音量设置为: " + level);
}
public void setSurroundSound() {
System.out.println("🔊 " + description + " 环绕立体声模式已开启");
}
public void setStereoSound() {
System.out.println("🔊 " + description + " 立体声模式已开启");
}
public int getVolume() {
return volume;
}
}
public class DVDPlayer {
private String description;
private String currentMovie;
public DVDPlayer(String description) {
this.description = description;
}
public void on() {
System.out.println("📀 " + description + " DVD播放器打开");
}
public void off() {
System.out.println("📀 " + description + " DVD播放器关闭");
}
public void play(String movie) {
this.currentMovie = movie;
System.out.println("📀 " + description + " 正在播放: \"" + movie + "\"");
}
public void pause() {
System.out.println("⏸️ " + description + " 暂停播放: \"" + currentMovie + "\"");
}
public void stop() {
System.out.println("⏹️ " + description + " 停止播放: \"" + currentMovie + "\"");
currentMovie = null;
}
public void eject() {
if (currentMovie != null) {
System.out.println("⏏️ " + description + " 弹出光盘: \"" + currentMovie + "\"");
currentMovie = null;
} else {
System.out.println("⏏️ " + description + " 弹出光盘");
}
}
}
public class PopcornPopper {
private String description;
public PopcornPopper(String description) {
this.description = description;
}
public void on() {
System.out.println("🍿 " + description + " 爆米花机打开");
}
public void off() {
System.out.println("🍿 " + description + " 爆米花机关闭");
}
public void pop() {
System.out.println("🍿 " + description + " 开始制作爆米花...");
System.out.println("🍿 爆米花制作完成!");
}
}
public class Projector {
private String description;
public Projector(String description) {
this.description = description;
}
public void on() {
System.out.println("📽️ " + description + " 投影仪打开");
}
public void off() {
System.out.println("📽️ " + description + " 投影仪关闭");
}
public void wideScreenMode() {
System.out.println("📽️ " + description + " 设置为宽屏模式 (16:9)");
}
public void normalMode() {
System.out.println("📽️ " + description + " 设置为标准模式 (4:3)");
}
}
public class Screen {
private String description;
public Screen(String description) {
this.description = description;
}
public void up() {
System.out.println("🎬 " + description + " 幕布收起");
}
public void down() {
System.out.println("🎬 " + description + " 幕布放下");
}
}
public class TheaterLights {
private String description;
private int brightness;
public TheaterLights(String description) {
this.description = description;
this.brightness = 100;
}
public void on() {
System.out.println("💡 " + description + " 灯光打开");
this.brightness = 100;
}
public void off() {
System.out.println("💡 " + description + " 灯光关闭");
this.brightness = 0;
}
public void dim(int level) {
this.brightness = level;
System.out.println("💡 " + description + " 灯光调暗至: " + level + "%");
}
public int getBrightness() {
return brightness;
}
}
外观模式核心类
public class HomeTheaterFacade {
private Amplifier amplifier;
private DVDPlayer dvdPlayer;
private Projector projector;
private TheaterLights lights;
private Screen screen;
private PopcornPopper popper;
/**
* 构造函数 - 注入所有子系统
*/
public HomeTheaterFacade(Amplifier amplifier,
DVDPlayer dvdPlayer,
Projector projector,
TheaterLights lights,
Screen screen,
PopcornPopper popper) {
this.amplifier = amplifier;
this.dvdPlayer = dvdPlayer;
this.projector = projector;
this.lights = lights;
this.screen = screen;
this.popper = popper;
}
/**
* 观看电影 - 封装了复杂的操作步骤
*/
public void watchMovie(String movie) {
System.out.println("\n🎬 ========== 准备观看电影 ==========");
System.out.println("📺 正在为您准备观影环境...\n");
// 1. 制作爆米花
popper.on();
popper.pop();
// 2. 调暗灯光
lights.dim(10);
// 3. 放下幕布
screen.down();
// 4. 打开投影仪
projector.on();
projector.wideScreenMode();
// 5. 打开功放
amplifier.on();
amplifier.setVolume(8);
amplifier.setSurroundSound();
// 6. 打开DVD播放器并播放电影
dvdPlayer.on();
dvdPlayer.play(movie);
System.out.println("\n✅ 准备完成,请尽情享受电影!");
}
/**
* 结束电影 - 封装了关闭所有设备的步骤
*/
public void endMovie() {
System.out.println("\n🎬 ========== 关闭影院系统 ==========");
System.out.println("📺 正在关闭所有设备...\n");
// 1. 关闭爆米花机
popper.off();
// 2. 调亮灯光
lights.on();
// 3. 收起幕布
screen.up();
// 4. 关闭投影仪
projector.off();
// 5. 停止DVD并关闭
dvdPlayer.stop();
dvdPlayer.eject();
dvdPlayer.off();
// 6. 关闭功放
amplifier.off();
System.out.println("\n✅ 所有设备已关闭,感谢观影!");
}
/**
* 暂停电影
*/
public void pauseMovie() {
System.out.println("\n⏸️ ========== 暂停电影 ==========");
dvdPlayer.pause();
lights.dim(50);
System.out.println("✅ 电影已暂停,灯光已调亮");
}
/**
* 继续电影
*/
public void resumeMovie(String movie) {
System.out.println("\n▶️ ========== 继续电影 ==========");
lights.dim(10);
dvdPlayer.play(movie);
System.out.println("✅ 电影继续播放");
}
/**
* 调整音量
*/
public void setVolume(int level) {
System.out.println("\n🔊 调整音量");
amplifier.setVolume(level);
}
/**
* 调整灯光
*/
public void setLights(int brightness) {
System.out.println("\n💡 调整灯光");
lights.dim(brightness);
}
}使用方式
public class Test {
public static void main(String[] args) {
System.out.println("=== 外观模式 - 家庭影院系统示例 ===\n");
// 创建所有子系统组件
Amplifier amplifier = new Amplifier("索尼5.1声道");
DVDPlayer dvdPlayer = new DVDPlayer("索尼蓝光");
Projector projector = new Projector("爱普生4K");
TheaterLights lights = new TheaterLights("智能灯光系统");
Screen screen = new Screen("电动投影幕布");
PopcornPopper popper = new PopcornPopper("爆米花机");
// ========== 对比:不使用外观模式 ==========
System.out.println("【场景1:不使用外观模式 - 手动操作所有设备】");
System.out.println("客户端需要了解所有子系统的细节,操作复杂:\n");
System.out.println("观影前需要执行以下步骤:");
System.out.println("1. popper.on()");
System.out.println("2. popper.pop()");
System.out.println("3. lights.dim(10)");
System.out.println("4. screen.down()");
System.out.println("5. projector.on()");
System.out.println("6. projector.wideScreenMode()");
System.out.println("7. amplifier.on()");
System.out.println("8. amplifier.setVolume(8)");
System.out.println("9. amplifier.setSurroundSound()");
System.out.println("10. dvdPlayer.on()");
System.out.println("11. dvdPlayer.play(movie)");
System.out.println("\n❌ 太复杂了!容易出错,用户体验差!");
// ========== 使用外观模式 ==========
System.out.println("\n\n【场景2:使用外观模式 - 简化操作】");
System.out.println("客户端只需要调用一个简单的方法:\n");
// 创建外观对象
HomeTheaterFacade homeTheater = new HomeTheaterFacade(
amplifier, dvdPlayer, projector, lights, screen, popper
);
// 测试1:观看电影
homeTheater.watchMovie("阿凡达2:水之道");
// 模拟观影过程
System.out.println("\n⏳ 电影播放中...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 测试2:暂停电影
homeTheater.pauseMovie();
// 模拟暂停时间
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 测试3:继续电影
homeTheater.resumeMovie("阿凡达2:水之道");
// 模拟继续观影
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 测试4:调整音量
homeTheater.setVolume(12);
// 测试5:调整灯光
homeTheater.setLights(20);
// 模拟观影结束
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 测试6:结束电影
homeTheater.endMovie();
System.out.println("\n\n=== 外观模式说明 ===");
System.out.println("1. 子系统: Amplifier、DVDPlayer等 - 各自独立的复杂系统");
System.out.println("2. 外观类: HomeTheaterFacade - 提供简化的统一接口");
System.out.println("3. 客户端: 只需要与外观类交互,无需了解子系统细节");
System.out.println("4. 封装性: 将复杂的操作序列封装在外观类中");
System.out.println("\n=== 外观模式优势 ===");
System.out.println("✅ 简化接口: 为复杂子系统提供简单接口");
System.out.println("✅ 降低耦合: 客户端与子系统解耦");
System.out.println("✅ 提高可用性: 用户无需了解系统内部结构");
System.out.println("✅ 更好的分层: 定义系统中每层的入口点");
System.out.println("✅ 灵活性: 客户端仍可直接访问子系统");
System.out.println("\n=== 外观模式应用场景 ===");
System.out.println("📌 复杂系统简化: 为复杂系统提供简单入口");
System.out.println("📌 分层架构: 定义各层之间的接口");
System.out.println("📌 遗留系统封装: 为老旧系统提供新接口");
System.out.println("📌 第三方库封装: 简化第三方API使用");
System.out.println("📌 微服务网关: API网关就是外观模式");
System.out.println("\n=== 外观模式 vs 适配器模式 ===");
System.out.println("外观模式: 简化接口,封装多个子系统");
System.out.println("适配器模式: 转换接口,让不兼容的接口协同工作");
System.out.println("\n=== 外观模式的最佳实践 ===");
System.out.println("✨ 最少知识原则: 客户端只与外观类交互");
System.out.println("✨ 保留灵活性: 仍允许直接访问子系统");
System.out.println("✨ 职责单一: 外观类只负责协调子系统");
System.out.println("✨ 可扩展性: 易于添加新的外观方法");
}
}
Last updated
Was this helpful?