简介
门面模式(Facade Pattern)又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型模式。
我们在生活中有很多地方也是用到了门面模式,但凡只要高层模块需要调用多个系统(2个以上类对象),我们都会自觉地创建一个新类封装这些子系统,提供精简接口,让高层模块可以更加容易间接调用这些子系统的功能。尤其是现阶段各种第三方SDK,更种开源类库,很大概率都会使用门面模式。
门面模式的应用场景
1、子系统越来越复杂,增加门面模式提供简单接口
2、构建多层系统结构,利用门面对象呢作为每层的入口,简化层间调用。
门面模式的UML图:
门面模式主要包含2种角色:
外观角色(Facade):也称门面角色,系统对外的统一接口;
子系统角色(SubSystem):可以同时有一个或多个SubSystem。每个SubSystem都不是一个单独的类,而是一个类的集合。SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另一个客户端而已(即Facade对SubSystem透明)。
门面模式在源码中的应用
1、Spring JDBC模块下的JdbcUtils类
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);
}
}
}
...
}
其他的方法:
2、Mybatis类中的Configuration类
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) 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) 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) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
public Executor newExecutor(Transaction transaction) {
return newExecutor(transaction, defaultExecutorType);
}
3、在Tomcat源码中也有使用,RequestFacade
类、ResponseFacade
类、StandardSessionFacade
类
门面模式的优缺点
优点:
1、简化了调用过程,无需深入了解子系统,以防给子系统带来风险
2、减少系统依赖、松散耦合
3、更好的划分访问层次,提高了安全性
4、遵守迪米特法则,即最少知道原则
缺点:
1、当增加子系统和扩展子系统行为时,可能容易带来未知风险
2、不符合开闭原则
3、某些情况下可能违背单一职责原则