定义
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
结构
- 模块,接受Facade的委派,真正实现功能。
- Facade,定义子系统的多个模块对外的高层接口,通常需要调用内部多个模块,将客户端的请求委派给适当的模块。
简单实现
模块A
public class AModule {
public void testA() {
System.out.println("this is A module");
}
}
模块B
public class BModule {
public void testB() {
System.out.println("this is B module");
}
}
外观类
public class Facade {
private AModule aModule;
private BModule bModule;
public Facade() {
this.aModule = new AModule();
this.bModule = new BModule();
}
public void test() {
aModule.testA();
bModule.testB();
}
}
客户端
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.test();
}
}
客户端和外观类交互,不需要知道子系统中模块的存在。
外观模式在Tomcat中的实现
Tomcat中的RequestFacade的实现
/**
* Facade class that wraps a Coyote request object.
* All methods are delegated to the wrapped request.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
@SuppressWarnings("deprecation")
public class RequestFacade implements HttpServletRequest {
/**
* Construct a wrapper for the specified request.
*
* @param request The request to be wrapped
*/
public RequestFacade(Request request) {
this.request = request;
}
@Override
public Object getAttribute(String name) {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return request.getAttribute(name);
}
}
客户端只需要和RequestFacade交互,不需要知道具体的实现Request类。
优缺点总结
优点
- 对客户端屏蔽了子系统的实现,子系统更加容易扩展和维护。
- 对客户端来说更加的简单易用,不需要了解子系统内部的实现。
缺点
- 过多的或者不合理的外观模式容易让人迷惑,到底是和Facade交互好还是直接和子系统交互好。
本质
外观模式的本质就是封装交互,简化调用。外观模式很好的体现了 最少知识原则,客户端只需要知道外观类,可以在不影响客户端的情况下,实现系统内部的维护和扩展。
我们项目中的service类中调用多个dao层的接口来实现功能,service类也可以看做外观模式的实现。
使用场景
- 想要为复杂的子系统提供一个简单的接口。
- 客户端和多个子系统存在耦合,引入外观类来解耦。
参考
大战设计模式【10】—— 外观模式
设计模式的征途—11.外观(Facade)模式
研磨设计模式-书籍