设计模式八之外观模式

外观模式(Facade)旨在简化复杂子系统的访问,提供一个统一接口,减少系统间的耦合。模式特点是简化调用过程,减少依赖,提高可维护性,但也可能导致扩展风险。在Spring框架中,JdbcUtils类即是一个外观模式的例子,用于封装java.sql的接口供客户端使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  软件系统中,当一个系统的功能越来越强,子系统会越来越多,客户端对系统的访问也会变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。

1. 模式的定义与特点

1.1 模式的定义

  外观模式(Facade):为多个复杂的子系统提供一个对外的接口,使这些子系统更加容易的被访问。该模式对外有一个统一的接口,外部应用不用关心子系统内部的细节,大大降低了应用程序的复杂度,提高了可维护性。

1.2 模式的特点

  外观模式是“迪米特法则(最少知道原则)“的典型应用,其优点为:
    1. 简化了调用过程,应用无需深入了解子系统;
    2. 减少系统依赖,松散耦合;
    3. 更好的划分访问层次;
    4. 符合迪米特法则,即最少知道原则。

  外观模式的缺点有:
    1. 增加子系统,扩展子系统行为容易引入风险;
    2. 不符合开闭原则。

1.3 模式的使用场景

  1. 子系统越来越复杂,增加外观模式提供简单调用接口;
  2. 构建多层系统结构,利用外观对象作为每层的入口,简化层级调用。

2. 模式的结构与实现

2.1 模式的结构

  外观模式的结构比较简单,主要定义了一个高层接口,它包含了对多个子系统的引用,客户端可以通过它来访问各个子系统的功能。外观模式包含以下主要角色:
    1. 外观角色(Facade):为多个子系统对外提供一个共同的接口;
    2. 子系统角色(Sub System):实现系统的部分功能,客户端可以通过外观角色访问它;
    3. 客户端角色(Client):通过外观角色访问各个子系统的功能。

外观模式类UML

2.2 模式的实现

/**
 * 礼品类
 */
public class Gift {

    private String name;

    public Gift(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

子系统角色

/**
 * 积分服务
 */
public class CoinService {

    /**
     * 检查积分是否足够兑换
     * @param gift
     * @return
     */
    public boolean isCoinEnough(Gift gift) {
        System.out.println("兑换" + gift.getName() + ",积分扣减成功");
        return true;
    }

}

/**
 * 库存服务
 */
public class InventoryService {

    /**
     * 扣减库存
     * @param gift
     * @return
     */
    public boolean deductInventory(Gift gift) {
        System.out.println("扣减" + gift.getName() + "库存成功");
        return true;
    }

}

/**
 * 物流服务
 */
public class LogisticsService {

    /**
     * 获取物流单号
     * @param gift
     * @return
     */
    public String getLogisticsNo(Gift gift) {
        System.out.println(gift.getName() + "进入物流系统");
        String logisticsNo = "555";
        return logisticsNo;
    }

}

外观角色

/**
 * 外观角色 - 礼品兑换服务
 */
public class GiftExchangeService {

    private CoinService coinService = new CoinService();
    private InventoryService inventoryService = new InventoryService();
    private LogisticsService logisticsService = new LogisticsService();

    public void giftExchange(Gift gift) {
        if (coinService.isCoinEnough(gift)) {
            if (inventoryService.deductInventory(gift)) {
                String logisticsNo = logisticsService.getLogisticsNo(gift);
                System.out.println("物流系统下单成功,物流单号为:" + logisticsNo);
            }
        }
    }

}

客户端

public class Client {

    public static void main(String[] args) {
        Gift gift = new Gift("航空母舰");
        GiftExchangeService giftExchangeService = new GiftExchangeService();
        giftExchangeService.giftExchange(gift);
    }
}

# 运行结果如下:
兑换航空母舰,积分扣减成功
扣减航空母舰库存成功
航空母舰进入物流系统
物流系统下单成功,物流单号为:555

3. 模式在开源软件中的应

3.1 org.springframework.jdbc.support.JdbcUtils 类

public abstract class JdbcUtils {
    public static final int TYPE_UNKNOWN = -2147483648;
    private static final Log logger = LogFactory.getLog(JdbcUtils.class);

    public JdbcUtils() {
    }

    public static void closeConnection(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(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(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);
            }
        }

    }
} 

  Spring JdbcUtils 提供了基于 java.sql 的统一公共接口,外部客户端通过该外观服务访问 java.sql 中的功能实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值