外观模式
定义
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
说白了,外观模式帮助我们屏蔽掉了代码背后复杂的逻辑,而是向用户提供简单的可以访问系统的接口去实现这些具体的复杂逻辑。举两个简单的小例子来帮助各位小伙伴理解外观模式的含义~
示例一:我们在开发应用系统时经常用到 Java 的三层架构(MVC),我们对外提供 controller 让页面去调用,但是 controller 内部可能调用了很多 service ,而 service 又调用了一些 mapper ,总之就是代码内部逻辑很复杂,但是对外只是一个简单干净的接口。
示例二:我们去银行办理银行卡的时候,总是会有一个银行的接待人员来帮助我们办理,因为办理银行卡的步骤相对繁琐一些,需要经过填表、录入信息等等流程才可以完成银行卡的办理。那么光靠用户自己去操作是非常耗时的,而且用户体验也会大大降低,所以银行给我们提供了一个接待员,接待员帮助我们规避了流程中的大部分繁琐操作,从而让我们在办卡的时候感觉到高效和便捷。
通过上面两个例子我们看出,当客户端不需要知道系统内部的复杂联系而只关心如何使用时,整个系统就需要提供一个"接待员"来规避系统内部复杂的业务逻辑,提供接待员的这个过程使用的就是外观模式。外观模式为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。它可以帮助我们降低访问复杂系统的内部子系统时的复杂度,简化客户端之间的接口,让系统之间(或前、后台之前)的调用更加便捷。
外观模式的实现
通过上面提到的办理银行卡的例子,我们可以看出外观模式主要分为了三个角色:
- 外观角色:糅合多个子系统功能,对外提供一个共同的接口,即银行接待员
- 子系统的角色:实现系统的部分功能,即办理银行卡时负责录入信息、制卡等操作的机器
- 客户角色:通过外观角色访问各个子系统的功能,即办理银行卡的用户
下面我们就用代码简单的实现一下外观模式
①将办理银行卡时的每个操作都抽象成一个组件
public interface Component {
public void work();
}
复制代码
②定义录入信息、制作卡片等组件,并分别实现接口
class InputInfo implements Component{
@Override
public void work() {
System.out.println("现在在录入用户基本信息~");
}
}
class InputPassword implements Component{
@Override
public void work() {
System.out.println("现在在录入银行卡密码~");
}
}
class MakingCard implements Component{
@Override
public void work() {
System.out.println("信息填写完毕,现在开始制做银行卡~");
}
}
复制代码
③以上组件是需要一起工作的,下面模拟一下办理银行卡的流程,让机器中的操作系统去分别调用他们
public class OperationSystem {
private Component inputInfo;
private Component inputPassword;
private Component makingCard;
public OperationSystem() {
this.inputInfo = new InputInfo();
this.inputPassword = new InputPassword();
this.makingCard = new MakingCard();
}
public void startingWork(){
System.out.println("开始办理银行卡~");
inputInfo.work();
inputPassword.work();
makingCard.work();
}
}
复制代码
④用户办理银行卡
public class Test {
public static void main(String[] args){
OperationSystem operationSystem = new OperationSystem();
operationSystem.startingWork();
}
}
复制代码
外观模式的优、缺点
最后我们总结一下外观模式的优点与缺点
优点
装饰器模式可以减少系统依赖(指的是对外的系统依赖);提高灵活性;提高安全性
缺点
把很多东西糅合到一起,可能会带来未知的风险;增加新的子系统可能需要修改外观类或者客户端的源代码,违反了“开闭原则”