返回
顶部

references:

https://github.com/iluwatar/java-design-patterns/tree/master/facade

facade这个单词的字面意思是“正面、外观”

举一个现实中的例子来更容易去理解这个模式的意图:

如果我问你金矿是怎么运作的,你可能会说,这很简单,矿工下去把金子挖出来就完事儿了

你这么说是因为你只看到了金矿向外暴露的样子

实际上金矿内部很复杂,想挖出金子还需要做很多其他的工作

==通过一个简单的接口来使用一个复杂的系统就是facade==

换句话说,Facade模式为一个复杂的系统提供了一个简单的接口

引用维基百科上的话,facade是一个对象,它为更大的代码体(比如类库)提供简化的接口

本示例的背景是矿工挖金矿

在程序的入口函数中,只有几行代码:

package com.iluwatar.facade;

public class App {
  public static void main(String[] args) {
    var facade = new DwarvenGoldmineFacade();
    facade.startNewDay();
    facade.digOutGold();
    facade.endDay();
  }
}

在获取到facade对象之后,只调用了三个方法

就像上面说过的,你只看到了矿工下去挖矿,然后金子被运出来,你并不了解内部的运作方式,正如主方法中调用的这三个方法:开始新的一天、挖金子、结束

facade为你隐藏了内部实现,你不需要关心他是怎么开始的新的一天,怎么挖的金子,怎么结束的一天,你只需要使用就行了

facade切断了终端用户与金矿子系统的依赖

在本例中,金矿子系统就是抽象类DwarvenMineWorker

package com.iluwatar.facade;

import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;

@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();
        break;
      case WAKE_UP:
        wakeUp();
        break;
      case GO_HOME:
        goHome();
        break;
      case GO_TO_MINE:
        goToMine();
        break;
      case WORK:
        work();
        break;
      default:
        LOGGER.info("Undefined action");
        break;
    }
  }

  /**
   * Perform actions.
   */
  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
  }
}

注意这段代码:

Arrays.stream(actions).forEach(this::action);

很明显,这段代码用到了昨天学习的函数式编程的思想

上面的代码相当于:

Arrays.stream(actions).forEach((action) -> this.action(action));

只不过是遍历方式简化了许多,再加上lambda表达式的简写,一眼看上去可能会不理解

定义完上面的矮人矿工抽象类之后,接着需要编写三个实体类:隧道挖掘工、矿工、运输工

每个实体类都会实现work()方法和name()方法,后者不重要,只是用来在演示的时候提供提示信息

不同的矿工拥有不同的work()实现,这些方法会在DwarvenGoldmineFacade类中被调用

这个设计模式其实还算比较好理解,就是复杂系统的内部实现对于用户是透明的,就像使用计算机,它只呈献给用户一个UI,但是具体内部实现原理是与用户隔绝的