门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用。
在 GoF 给出的定义中提到,“门面模式让子系统更加易用”,实际上,它除了解决易用性问题之外,还能解决例如性能问题,分布式事务问题等,门面模式定义中的“子系统(subsystem)”也可以有多种理解方式。它既可以是一个完整的系统,也可以是更细粒度的类或者模块。
public class SubSystemA{
public void doA(){
System.out.println("doing A stuff");
}
}
public class SubSystemB{
public void doB(){
System.out.println("doing B stuff");
}
}
public class SubSystemC{
public void doC(){
System.out.println("doing C stuff");
}
}
然后,创建外观角色Facade类:
public class Facade{
private SubSystemA a = new SubSystemA();
private SubSystemB b = new SubSystemB();
private SubSystemC c = new SubSystemC();
//对外接口
public void doA(){
this.a.doA();
}
//对外接口
public void doB(){
this.b.doB();
}
//对外接口
public void doC(){
this.c.doC();
}
}
来看客户端代码:
public static void main(String[] args){
Facade facede = new Facade();
facade.doA();
facade.doB();
facade.doC();
}
1.4、门面模式在源码中的应用
public abstract class JdbcUtils {
public static final int TYPE_UNKNOWN = -2147483648;
private static final Log logger = LogFactory.getLog(JdbcUtils.class);
private static final Map<Integer, String> typeNames = new HashMap();
public JdbcUtils() {
}
public static void closeConnection(@Nullable Connection con) {
if (con != null) {
try {
con.close();
} catch (SQLException var2) {
logger.debug("Could not close JDBC Connection", var2);
} catch (Throwable var3) {
logger.debug("Unexpected exception on closing JDBC Connection", var3);
}
}
}
public static void closeStatement(@Nullable Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException var2) {
logger.trace("Could not close JDBC Statement", var2);
} catch (Throwable var3) {
logger.trace("Unexpected exception on closing JDBC Statement", var3);
}
}
}
public static void closeResultSet(@Nullable ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException var2) {
logger.trace("Could not close JDBC ResultSet", var2);
} catch (Throwable var3) {
logger.trace("Unexpected exception on closing JDBC ResultSet", var3);
}
}
}
...
}
再来看一个MyBatis中的Configuration类。它其中有很多new开头的方法,来看一下源代码:下面的这些方法都是对JDBC中关键组件操作的封装。
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, this.objectFactory, this.objectWrapperFactory, this.reflectorFactory);
}
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler)this.interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
ResultSetHandler resultSetHandler = (ResultSetHandler)this.interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
StatementHandler statementHandler = (StatementHandler)this.interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
public Executor newExecutor(Transaction transaction) {
return this.newExecutor(transaction, this.defaultExecutorType);
}
...
另外地在Tomcat的源码中也有体现,也非常的有意思。举个例子RequestFacade类,来看源码:
public class RequestFacade implements HttpServletRequest {
...
public String getContentType() {
if (this.request == null) {
throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
} else {
return this.request.getContentType();
}
}
public ServletInputStream getInputStream() throws IOException {
if (this.request == null) {
throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
} else {
return this.request.getInputStream();
}
}
public String getParameter(String name) {
if (this.request == null) {
throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
} else {
return Globals.IS_SECURITY_ENABLED ? (String)AccessController.doPrivileged(new RequestFacade.GetParameterPrivilegedAction(name)) : this.request.getParameter(name);
}
}
public Enumeration<String> getParameterNames() {
if (this.request == null) {
throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
} else {
return Globals.IS_SECURITY_ENABLED ? (Enumeration)AccessController.doPrivileged(new RequestFacade.GetParameterNamesPrivilegedAction()) : this.request.getParameterNames();
}
}
...
}
我们看名字就知道他用了门面模式。它封装了非常多的request的操作,也整合了很多servlet-api以外的一些内容,给用户提供了很大的便捷。同样,Tomcat对Response和Session当也封装了ResponseFacade和StandardSessionFacade类,感兴趣的小伙伴可以去深入了解一下。
二、参考链接:
https://blog.csdn.net/Liuxiangming1314/article/details/124391997
https://www.jianshu.com/p/4a5966659237