Java 中的 Facade 模式:简化复杂系统接口
大约 4 分钟
Facade 设计模式的意图
Facade 设计模式为子系统中的一组接口提供了一个统一的接口。这种 Java 设计模式简化了复杂的系统交互。
Facade 模式的详细解释以及现实世界示例
现实世界示例
想象一个家用影院系统,它包含多个组件:DVD 播放器、投影仪、环绕声系统和灯光。每个组件都有一个复杂的接口,包含许多功能和设置。为了简化家用影院系统的使用,提供了一个遥控器(即 Facade)。遥控器提供了一个统一的界面,包含“播放电影”、“停止”、“暂停”和“音量增大/减小”等简单的按钮,这些按钮在内部与各个组件通信,管理它们的交互。这样可以使系统更易于使用,而无需了解每个组件的详细操作。
简单来说
Facade 模式为复杂子系统提供了一个简化的接口。
维基百科说
Facade 是一个对象,它为一个更大的代码体(例如类库)提供了一个简化的接口。
Java 中 Facade 模式的编程示例
以下是在金矿场景中使用 Facade 设计模式的示例,演示了 Java facade 如何简化复杂操作。
金矿是如何运作的?“嗯,矿工下去挖金子!”你说。你之所以这样认为是因为你使用了金矿在外部提供的简单接口,而内部要进行很多工作才能做到这一点。这个对复杂子系统的简单接口就是一个 facade。
这里我们有矮人矿工层次结构。首先,有一个基类 DwarvenMineWorker
@Slf4j
public abstract class DwarvenMineWorker {
public void goToSleep() {
LOGGER.info("{} goes to sleep.", name());
}
public void wakeUp() {
LOGGER.info("{} wakes up.", name());
}
public void goHome() {
LOGGER.info("{} goes home.", name());
}
public void goToMine() {
LOGGER.info("{} goes to the mine.", name());
}
private void action(Action action) {
switch (action) {
case GO_TO_SLEEP -> goToSleep();
case WAKE_UP -> wakeUp();
case GO_HOME -> goHome();
case GO_TO_MINE -> goToMine();
case WORK -> work();
default -> LOGGER.info("Undefined action");
}
}
public void action(Action... actions) {
Arrays.stream(actions).forEach(this::action);
}
public abstract void work();
public abstract String name();
enum Action {
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
}
}
然后我们有具体的矮人类 DwarvenTunnelDigger
、DwarvenGoldDigger
和 DwarvenCartOperator
@Slf4j
public class DwarvenTunnelDigger extends DwarvenMineWorker {
@Override
public void work() {
LOGGER.info("{} creates another promising tunnel.", name());
}
@Override
public String name() {
return "Dwarven tunnel digger";
}
}
@Slf4j
public class DwarvenGoldDigger extends DwarvenMineWorker {
@Override
public void work() {
LOGGER.info("{} digs for gold.", name());
}
@Override
public String name() {
return "Dwarf gold digger";
}
}
@Slf4j
public class DwarvenCartOperator extends DwarvenMineWorker {
@Override
public void work() {
LOGGER.info("{} moves gold chunks out of the mine.", name());
}
@Override
public String name() {
return "Dwarf cart operator";
}
}
为了操作所有这些金矿工人,我们有 DwarvenGoldmineFacade
public class DwarvenGoldmineFacade {
private final List<DwarvenMineWorker> workers;
public DwarvenGoldmineFacade() {
workers = List.of(
new DwarvenGoldDigger(),
new DwarvenCartOperator(),
new DwarvenTunnelDigger());
}
public void startNewDay() {
makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);
}
public void digOutGold() {
makeActions(workers, DwarvenMineWorker.Action.WORK);
}
public void endDay() {
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
}
private static void makeActions(Collection<DwarvenMineWorker> workers,
DwarvenMineWorker.Action... actions) {
workers.forEach(worker -> worker.action(actions));
}
}
现在让我们使用 facade
public static void main(String[] args) {
var facade = new DwarvenGoldmineFacade();
facade.startNewDay();
facade.digOutGold();
facade.endDay();
}
程序输出
06:07:20.676 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger wakes up.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes to the mine.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator wakes up.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes to the mine.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger wakes up.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes to the mine.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenGoldDigger -- Dwarf gold digger digs for gold.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenCartOperator -- Dwarf cart operator moves gold chunks out of the mine.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenTunnelDigger -- Dwarven tunnel digger creates another promising tunnel.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes home.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes to sleep.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes home.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes to sleep.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes home.
06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes to sleep.
何时在 Java 中使用 Facade 模式
在以下情况下使用 Java 中的 Facade 模式
- 你想为复杂子系统提供一个简单的接口。
- 子系统变得越来越复杂,并且依赖于多个类,但大多数客户只需要一部分功能。
- 需要对子系统进行分层。使用 facade 定义每个子系统级别的入口点。
- 你想减少依赖并提高 Java 开发中的代码可读性。
Facade 模式 Java 教程
- Java 中的 Facade 设计模式(DigitalOcean)
- Facade(重构 Guru)
- Facade 方法设计模式(GeekforGeeks)
- 设计模式 - Facade 模式(TutorialsPoint)
Java 中 Facade 模式的现实世界应用
- Java 库(如 java.net.URL 和 javax.faces.context.FacesContext)使用 Facade 来简化复杂的底层类。
- 在许多 Java 框架中,facade 用于通过为更复杂的底层代码结构提供更简单的接口来简化 API 的使用。
Facade 模式的优点和权衡
优点
在 Java 中实现 Facade 设计模式
- 将客户与子系统组件隔离开来,使使用更方便,并减少依赖关系。
- 促进子系统与其客户之间的松耦合。
- 通常简化了复杂系统的 API。
权衡
- 如果 Facade 的实现不正确,它可能会变成一个与应用程序中所有类耦合的“上帝对象”。
相关的 Java 设计模式
- Adapter:Facade 提供了一个统一的接口,而 Adapter 使两个现有接口能够协同工作。
- Mediator:Facade 定义了对子系统的更简单接口,而 Mediator 集中控制对象之间的复杂通信和控制。