模式动机
在软件系统中,客户端程序经常会与复杂系统的内部子系统之间产生耦合,从而导致客户端程序随子系统的变化而变化,那么如何简化客户端程序跟内部子系统之间的依赖?此时,我们需要引入一个“外观”角色,客户端直接与外观角色进行交互,客户端与子系统之间的依赖关系由外观角色(Facade)来实现和维护。如下图:
模式定义
外部程序与子系统之间的通信通过一个统一的外观对象进行,外观模式定义了一个高层的接口,为子系统中的一组接口提供一个一致的界面,使得子系统更加容易使用。外观模式也叫做门面模式。
模式结构
外观模式主要由以下两部分组成:
外观角色:如Facade
子系统:如SubSystemA
代码实现
假设现在有这样一个场景,一个客户去银行办理一张信用卡,假定银行工作人员需要进行三步操作,涉及到三个子系统。第一步:首先进行联网核查,看公安局系统里面是否存在这个人;第二步:通过个人信用系统查看此人是否有不良信用记录;第三步:进入银行系统,为此人办理信用卡。代码如下:
公安系统
public class UserSystem {
public boolean checkUser(int userId){
System.out.println("公安局系统查看是否存在此人!");
return true;
}
}
个人信用系统
public class CreditSystem {
public boolean checkCredit(int userId){
System.out.println("个人信用系统查看此人是否有不良信用记录!");
return true;
}
}
银行系统
public class BankSystem {
public void handle(int userId){
System.out.println("银行系统办理此业务!");
}
}
首先,我们先看不使用外观模式时,客户端如何实现:
public class Client {
public static void main(String[] args) {
int userId = 1;
BankSystem bs = new BankSystem();
CreditSystem cs = new CreditSystem();
UserSystem us = new UserSystem();
boolean b = true;
if(us.checkUser(userId)==false){//调用公安系统
b = false;
}else if(cs.checkCredit(userId)==false){//调用个人行用系统
b = false;
}
if(b){
bs.handle(userId);//调用银行系统
}
}
}
可以看到,此时客户端程序与三个子系统都发生了耦合,当子系统发生变化时,客户端程序也可能会面临着修改。如果子系统繁多且关系复杂时,客户端程序是很难进行维护的。一个比较好的设计是为这些子系统提供一个统一的接口,这个接口专门负责维护客户端与子系统之间以及各个子系统之间的依赖关系,客户端只需要跟这个统一的接口打交道即可。下面我们引入“外观”角色,使用外观模式来处理。
首先加入一个外观对象Facade
public class Facade {
private BankSystem bs = new BankSystem();
private CreditSystem cs = new CreditSystem();
private UserSystem us = new UserSystem();
public boolean handleCreditCard(int userId){
boolean b = true;
if(us.checkUser(userId)==false){
b = false;
}else if(cs.checkCredit(userId)==false){
b = false;
}
if(b){
bs.handle(userId);
}
return b;
}
}
修改客户端,使用外观角色
public class FacadeClient {
public static void main(String[] args) {
int userId = 1;
Facade facade = new Facade();
boolean handleResult = facade.handleCreditCard(userId);
System.out.println(handleResult);
}
}
可以看到,使用外观模式之后,客户端程序只与外观角色Facade发生耦合,屏蔽了与子系统之间的复杂关系,降低了客户端与子系统之间的耦合度。
总结
当我们的系统中存在多个子系统,客户端与子系统之间依赖性较大时,外观模式可以很好的降低耦合度。主要手段是通过引入一个外观角色(Facade),把客户端与子系统之间的依赖关系封装到这个外观对象中,客户端直接与外观对象进行交互。