Geek

博客园 首页 新随笔 联系 订阅 管理

外观模式,又叫门面模式 (符合迪米特法则,也就是最少知道原则, 不改让用户知道的,就别让其知道)

外观模式定义了高层的接口,子系统负责去实现

定义一个优秀的结构很重要

 

用户通过调用高层接口(门面),来达到自己的目的,而接口的实现是交给子系统去完成

用户不需要知道有哪些子系统(实现类或者是其他的类)

 

门面模式的使用场景:

子系统复杂,使用外观模式,提供统一简单调用的接口(架构师定义接口,由码农去实现)

目的:构建多层系统结构,利用外观对象作为每层的入口,简化层之间的调用

优点: 简化调用过程,无需了解深入子系统,防止带来风险

也减少了系统以来,降低耦合

提供更好的划分访问层次

 

外观模式的缺点:

增加子系统,扩展子系统行为容易引入风险

也不符合开闭原则

 

和外观模式相关的设计模式:

  1. 中介者模式(外观关注的是系统对外提供的接口(对外交互),而中介者是系统内部交互)
  2. 单例模式 (外观对象可以是一个单例对象)
  3. 抽象工厂模式 (外观类可以是一个抽象工厂,去获得子系统相关的实现(接口的实现类)) 比如 Logger log = LoggerFactory.getLogger(A.class); 子系统通过外观类,屏蔽了外部的访问,调用者无需关注实现

 

 

 

 

 

门面模式 在 tomcat,mybatis 以及 jdbcTemplate中 都有很好的应用

 

比如 tomcat 中的 RequestFacade implements HttpServletRequest

ctrl +n > 输入 requestFacade

 

 

可以看到优秀的设计,综合了 Façade和 装饰者模式

 

 

 

转到 JdbcUtils 代码下面

 

@Nullable

public static Object getResultSetValue(ResultSet rs, int index, @Nullable Class<?> requiredType) throws SQLException {

if (requiredType == null) {

return getResultSetValue(rs, index);

} else if (String.class == requiredType) {

return rs.getString(index);

} else {

Object value;

if (Boolean.TYPE != requiredType && Boolean.class != requiredType) {

if (Byte.TYPE != requiredType && Byte.class != requiredType) {

if (Short.TYPE != requiredType && Short.class != requiredType) {

if (Integer.TYPE != requiredType && Integer.class != requiredType) {

if (Long.TYPE != requiredType && Long.class != requiredType) {

if (Float.TYPE != requiredType && Float.class != requiredType) {

if (Double.TYPE != requiredType && Double.class != requiredType && Number.class != requiredType) {

if (BigDecimal.class == requiredType) {

return rs.getBigDecimal(index);

}

 

if (Date.class == requiredType) {

return rs.getDate(index);

}

 

if (Time.class == requiredType) {

return rs.getTime(index);

}

 

if (Timestamp.class != requiredType && java.util.Date.class != requiredType) {

if (byte[].class == requiredType) {

return rs.getBytes(index);

}

 

if (Blob.class == requiredType) {

return rs.getBlob(index);

}

 

if (Clob.class == requiredType) {

return rs.getClob(index);

}

 

if (requiredType.isEnum()) {

Object obj = rs.getObject(index);

if (obj instanceof String) {

return obj;

}

 

if (obj instanceof Number) {

return NumberUtils.convertNumberToTargetClass((Number)obj, Integer.class);

}

 

return rs.getString(index);

}

 

try {

return rs.getObject(index, requiredType);

} catch (AbstractMethodError var5) {

logger.debug("JDBC driver does not implement JDBC 4.1 'getObject(int, Class)' method", var5);

} catch (SQLFeatureNotSupportedException var6) {

logger.debug("JDBC driver does not support JDBC 4.1 'getObject(int, Class)' method", var6);

} catch (SQLException var7) {

logger.debug("JDBC driver has limited support for JDBC 4.1 'getObject(int, Class)' method", var7);

}

 

String typeName = requiredType.getSimpleName();

if ("LocalDate".equals(typeName)) {

return rs.getDate(index);

}

 

if ("LocalTime".equals(typeName)) {

return rs.getTime(index);

}

 

if ("LocalDateTime".equals(typeName)) {

return rs.getTimestamp(index);

}

 

return getResultSetValue(rs, index);

}

 

return rs.getTimestamp(index);

}

 

value = rs.getDouble(index);

} else {

value = rs.getFloat(index);

}

} else {

value = rs.getLong(index);

}

} else {

value = rs.getInt(index);

}

} else {

value = rs.getShort(index);

}

} else {

value = rs.getByte(index);

}

} else {

value = rs.getBoolean(index);

}

 

return rs.wasNull() ? null : value;

}

}

 

 

这个jdbcUtils 对 jdbc 进行了封装,在开发中,我们不需要关注怎么操作,直接用这个 jdbcUtils 即可

都是对原生 jdbc的封装

 

mybatis 的Configuration 中也是这样

 

Configuration 还结合 工厂模式, 通过这个工厂创建对应的实现类(实现了某个接口),然后返回给用户

 

posted on 2020-03-24 15:17  .geek  阅读(441)  评论(0编辑  收藏  举报