目录

[TOC]

什么是外观模式

外观模式又叫门面模式

外观模式也叫门面模式,在创建型模式、结构型模式和行为型模式分类中,外观模式归属于结构型模式

在我们实际的工作中,外观模式是最常用的一种设计模式之一

比如,我们把几个方法中共用的逻辑抽象成一个独立的方法,那么这个方法就可以理解成外观模式

外观模式是通过引入一个外观角色来简化调用者与各个子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与调用者的耦合度,使得扩展更加方便

img

外观模式实现步骤:

  1. 抽象各个子系统的业务逻辑
  2. 将抽象过的业务逻辑封装到门面类中
  3. 调用者使用门面类中的方法完成自己的逻辑

应用场景

  1. 需要为一个复杂的子系统提供一系列逻辑支持的时候,可以考虑使用外观模式,比如,上文中提到的案例。中台系统需要给业务系统提供多个方法支持,可以用外观模式
  2. 当调用者需要调用多个子系统来完成自己的逻辑时,可以考虑使用外观模式,比如日志处理框架 SLF4J,它对调用者提供接口。logbacklog4j等各种日志框架作为子系统去实现这些接口,业务系统需要记录日志时,调用SLF4J门面类即可,而不必关心具体使用的是哪一个框架

图文解释

假如我们有一个中台系统,系统中有5个接口供业务系统调用

image-20230627164824991

业务系统A需要调用中台系统的前三个接口完成自己的业务逻辑

业务系统B需要调用中台系统的后两个接口来完成业务系统B自己的逻辑

image-20230627164950400

接着是业务系统C、D、E、F等等,他们都和业务系统A或B的需求一样:希望调用中台系统的前三个接口或后两个接口去实现自己系统的业务逻辑

我们会发现,这些业务系统在调用中台系统时存在几个问题

  • 业务系统需要足够了解中台系统的每个接口逻辑,才能决定自己到底该调用哪些接口
  • 业务系统在调用中台系统接口时,需要调用多个接口,非常麻烦
  • 多个业务系统存在相同的代码,导致整体工作量增加

我们可以这样对中台系统进行改造,让业务系统调用更简单

image-20230627165113360

在中台系统中增加接口A ,在接口A里面分别分别调用接口1、2、3。业务系统A可以直接调用接口A来完成自己的业务

同样的,中台系统中增加接口B,在接口B中分别调用接口4、5。业务系统B可以直接调用接口B来完成自己的业务

这样我们就解决了刚才所说的3个问题

  • 业务系统不需要了解中台系统具体的接口逻辑,只需要调用对应的接口即可
  • 业务系统调用中台系统时不再是多个接口,只需要调用一个接口
  • 原来的多个业务系统中相同的代码被封装在了接口A或接口B中,业务系统相应的工作量会减少

这种实现方式就是在中台系统中使用了外观模式,接口A和接口B就是中台系统的门面(外观模式也叫门面模式)

代码

首先是中台系统的5个接口,这里用5个方法代表接口

1
2
3
4
5
6
7
public class Center {
public void method1(){} // 模拟接口1
public void method2(){} // 模拟接口2
public void method3(){} // 模拟接口3
public void method4(){} // 模拟接口4
public void method5(){} // 模拟接口5
}

接下来是中台系统中的外观类,里面包含了接口A和接口B。同样用两个方法来代表接口

在接口A中调用了中台系统的前3个方法;在接口B中调用了中台系统中的后两个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class CenterFacade {
private Center center = new Center();

// 模拟接口A
public void centerA() {
center.method1();
center.method2();
center.method3();
}

// 模拟接口B
public void centerB() {
center.method4();
center.method5();
}
}

业务系统A在调用时,使用外观类中的接口A即可实现自己的业务逻辑

1
2
CenterFacade centerFacade = new CenterFacade();
centerFacade.centerA();

业务系统B在调用时,使用外观类中的接口B即可实现自己的业务逻辑

1
2
CenterFacade centerFacade = new CenterFacade();
centerFacade.centerB();

总结

  • 优点

    • 外观模式给各个子系统提供统一的入口,调用者使用起来很简单
    • 外观模式把各个子系统和调用者解耦,扩展性会更好。比如,想要增加一个子系统时,只需要按照外观模式的规范进行开发,调用者和外观类都不用修改
  • 缺点

    • 如果设计不合理,增加新的子系统时可能需要修改外观类或调用者的源代码,违背了“开闭原则”