设计模式之简单化_Facade外观模式_简单窗口
前言
Github:https://github.com/HealerJean
一、外观模式(Facade Pattern)
1、模式概述
外观模式 是一种 结构型设计模式,它为 复杂的子系统提供一个统一的高层接口,使得子系统更易于使用。 外观(Facade)就像一个“接待员”或“门面”,屏蔽内部细节,只暴露简单、清晰的操作入口。
核心思想:“复杂藏在幕后,简单摆在台前。”
外观模式 = 简化入口 + 隐藏复杂:
- 它不是“减少代码”,而是“减少认知负担”。
类比理解:
- 去医院看病:
- 患者要自己挂号 → 门诊 → 划价 → 缴费 → 取药……流程繁琐;
- 如果有 导诊护士 统一协调,患者只需说“我头疼”,其余交给她处理——这就是 外观模式!
- 开车:发动机、变速箱、点火系统协同工作,但你只需转动钥匙 + 踩油门,无需懂机械原理。
2、使用场景
外观模式适用于以下情况:
- 子系统 非常复杂 或 难以理解,需要提供一个简单的入口;
- 系统中存在 大量相互依赖的类,客户端直接调用容易出错;
- 你需要 分层架构,将子系统与客户端解耦;
- 希望 封装遗留系统,对外提供现代化接口。
典型应用:
- 操作系统 API(如
File.open()封装底层 I/O); - 框架中的工具类(如
Spring的JdbcTemplate); - 微服务网关(Gateway 聚合多个服务调用);
- 游戏引擎的启动器(一键初始化音频、图形、物理模块)。
3、示例程序:图形绘制外观
1)子系统接口 Shape
/**
* 子系统公共接口(可选)
*/
public interface Shape {
void draw();
}
2)子系统实现类
a、圆形
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle::draw()");
}
}
b、矩形
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}
c、正方形
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Square::draw()");
}
}
3)外观类 ShapeMaker
/**
* 外观类(Facade)
* 封装图形子系统的复杂性,提供简单接口
*/
public class ShapeMaker {
private final Shape circle;
private final Shape rectangle;
private final Shape square;
public ShapeMaker() {
// 初始化子系统组件
this.circle = new Circle();
this.rectangle = new Rectangle();
this.square = new Square();
}
// 高层接口:隐藏内部调用细节
public void drawCircle() {
circle.draw();
}
public void drawRectangle() {
rectangle.draw();
}
public void drawSquare() {
square.draw();
}
// 可扩展:组合操作
public void drawAllShapes() {
drawCircle();
drawRectangle();
drawSquare();
}
}
4)客户端测试 Main
- 客户端 无需知道
Circle、Rectangle等类的存在; - 若子系统重构(如改名、拆分),只需修改
ShapeMaker,客户端零改动。
/**
* 客户端(Client)
* 只与外观类交互,完全 unaware 子系统细节
*/
public class Main {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();
// 简单调用
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
System.out.println("\n=== 一键绘制所有图形 ===");
shapeMaker.drawAllShapes();
}
}
输出:
Circle::draw()
Rectangle::draw()
Square::draw()
=== 一键绘制所有图形 ===
Circle::draw()
Rectangle::draw()
Square::draw()
5)模式角色
- 客户端 只知道 Facade;
- Facade 知道所有子系统;
- 子系统 彼此可能耦合,但对客户端透明。
| 角色 | 职责 | 示例 |
|---|---|---|
| Facade(外观类) | 提供统一的高层接口,封装子系统调用 | ShapeMaker |
| Subsystem Classes(子系统类) | 实现具体功能,但对客户端隐藏 | Circle, Rectangle, Square |
| Client(客户端) | 通过外观类与子系统交互,不直接访问子系统 | Main |
┌──────────────┐
│ Client │
└───────┬──────┘
│ uses
┌───────▼──────┐
│ ShapeMaker │<──────────┐
│ (Facade) │ │
├──────────────┤ │
│ - circle │ │
│ - rectangle │ │
│ - square │ │
└───────┬──────┘ │
│ │
┌──────────────┼──────────────────┼──────────────┐
│ │ │ │
┌────────▼───────┐ ┌────▼──────────┐ ┌─────▼────────┐ ┌───▼──────────┐
│ Circle │ │ Rectangle │ │ Square │ │ ...其他 │
└────────────────┘ └───────────────┘ └──────────────┘ └──────────────┘
▲ ▲ ▲
└──────────────────┴─────────────────┘
implements
┌────────────┐
│ Shape │
└────────────┘
4、FQA
1)外观模式 vs 建造者模式
- Builder 是“生产者”:关注 如何一步步造出一个对象;
- Facade 是“接待员”:关注 如何让别人轻松使用一堆现成的对象。
| 模式 | 目的 | 是否创建对象 | 关注点 |
|---|---|---|---|
| 建造者模式(Builder) | 构建复杂对象,支持不同配置生成不同产品 | ✅ 创建新对象 | 对象的构造过程 |
| 外观模式(Facade) | 简化已有系统的使用,不创建新对象 | ❌ 不创建(仅组合已有对象) | 系统的使用接口 |
2)模式优点
- 降低耦合度:客户端与子系统解耦;
- 提高易用性:提供简洁、语义清晰的接口;
- 便于维护:子系统变更不影响客户端;
- 支持分层开发:前端/后端可通过外观隔离。
3)注意事项
- 可能违背单一职责原则:外观类承担过多协调逻辑;
- 过度封装风险:若子系统本身不复杂,使用外观属于冗余;
- 灵活性降低:客户端无法细粒度控制子系统(如只初始化部分组件)


