目的
看脸模式目的很简单,就是给用户留个好印象,不想让用户关注系统中的具体细节,关注系统的外表(暴露出来的接口)就好了。一些 GUI 的菜单也好,SDK 也好或多或少也会用到这种思想。这更多的是一种思想,也没有说一定这样实现才是外观模式的 。参考维基百科的例子,电脑有 cpu、内存、磁盘等组成,cpu 有逻辑运算部分、有取指令部分;内存要负责存储指令数据;磁盘要控制磁道等等,这些都不是用户关心的,用户需要一个开机按钮罢了。
在《深入剖析 Tomcat》(英文名:《How tomcat works》)中也介绍了一下 Tomcat 中 Facade 模式的使用,下面来看看Tomcat 中 Facade 模式吧
Tomcat 中的 Facade 模式
Tomcat 中的 Facade 模式弄得有点像代理模式的。场景是这样的,Tomcat 中 Request 除了实现了 ServletRequest 接口外,还会有额外的一些函数,而这些函数需要被其他类调用,但这些方法不应该暴露给上层,因为上层应该专注于 ServletRequest 的实现。于是在 Tomcat 中会使用 Facade 模式了。
原来的 process 处理请求是这样的
public class ServletProcess {
public void process(Request request, Response response){
//....
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request, (ServletResponse) response);
}
}
而使用 Facade 后是这样
public class ServletProcess {
public void process(Request request, Response response){
//....
RequestFacade requestFacade = new RequestFacade(request);
ResponseFacade responseFacade = new ResponseFacade(response);
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
}
}
为了达到这种效果,RequestFacade 使用了类似代理模式的实现方式。
public class RequestFacade implements HttpServletRequest {
private ServletRequest request;
public RequestFacade(ServletRequest request) {
this.request = request;
}
@Override
public String getAuthType() {
return request.getAuthType();
}
}
对象里有个 ServletRequest 对象,而 RequestFacade 的所有方法都会委托给 ServletRequest 调用。
当然,逐个函数手动写委托调用好烦,好浪费时间的,我推荐使用了 lombok ,像是魔法一样,轻轻一个 @Delegate 就完事了
public class RequestFacade implements HttpServletRequest {
@Delegate
private ServletRequest request;
}
用 UML 分析是这样的,未使用 Facade 模式前
使用 Facade 模式之后