门面模式详解

门面模式详解门面模式门面模式 FacadePatter 又叫外观模式 提供了一个统一的接口 提供了一个统一的接口 用来访问子系统中的一群接口 其主要特征是定义了一个高层接口 让子系统更容易使用 属于结构性模式 其实 在我们日常的编码过程中 我们都在有意无意地大量使用门面模式 但凡只要高层模块需要调度多个子系统 2 个以上类对象 我们都会自觉地创建一个新类封装这些子系统 提供精密接口 让高层模块可以更加容易简介调用这些子系统的功能 尤其是现阶段各种第三方 SDK 各种块原类库 很大概率都会使用门面模式 尤其是你觉得

门面模式

门面模式的应用场景

门面模式的通用写法

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(); } 

门面模式业务场景实例

@Data public class GiftInfo{ 
    private String name; } 

然后,编写各个子系统的业务逻辑代码,分别创建积分系统QualifyService类:

public class QualifyService{ 
    public boolean isAvailable(GiftInfo giftInfo){ 
    System.out.println("校验"+giftInfo.getName()+"积分资格通过,库存通过"); } } 

支付系统PaymentService类:

public class PaymentService{ 
    public boolean pay(GiftInfo pointsGift){ 
    //扣减积分 System.out.println("支付"+pointsGift.getName()+"积分成功"); return true; } } 

物流系统ShippingService类:

public class shippingService{ 
    //发货 System.out.println(giftInfo.getName()+"进入物流系统"); String shippingOrderNo = "666"; return shippingOrderNo; } 

然后创建外观角色GiftFacadeService类,对外只开放一个月换礼物的exchange()方法,在exchange()方法内部整合3个子系统的所有功能。

public class giftFacadeService{ 
    private QualifyService qualifyService = new QualifyService(); private PaymentService paymentService = new PaymentService(); private ShippingService shippingService = new ShippingService(); public void exchange(GiftInfo giftInfo){ 
    if(qualifyService.isAvailable(giftInfo)){ 
    if(paymentService.pay(giftInfo)){ 
    String shippingNo = shippingService.delivery(giftInfo); System.out.println("物流系统下单成功,物流单号是:" + shippingNo); } } } } 

最后,来看客户端代码:

public class Test { 
    public static void main(String[] args) { 
    FacadeService facadeService = new FacadeService(); GiftInfo giftInfo = new GiftInfo("《Spring 5核心原理》"); facadeService.exchange(giftInfo); } } 

门面模式在源码中的应用

 下面我们来门面模式在源码中的应用,先来看Spring JDBC模块下的JdbcUtils类,它封装了和JDBC相关的所有操作,它一个代码片段: 
public abstract class JdbcUtils { 
    public static final int TYPE_UNKNOWN = -; 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开头的方法,来看一下源代码:

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); } ... 

上面的这些方法都是对JDBC中关键组件操作的封装。另外地在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://javaforall.net/224750.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午11:14
下一篇 2026年3月17日 上午11:14


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号