7. 外观模式(Facade Pattern)

定义

  • 外观模式又叫门面模式,提供了一个统一的接口,用了访问子系统中的一群接口
  • 外观模式定义了一个高层接口,让子系统更容易使用

类型

结构型

组成

  • 外观角色:了解子系统所有的方法,它也有自己的方法,客户端通过调用外观角色的方法来调用子系统的功能
  • 子系统:可以是一个也可以是多个,子系统按照不同的维度,完成不同的处理模块,并不是单独的类,子系统形成一个集合,为外观模式的外观了类,提供子系统的功能

优点

  • 简化了调用过程,无需了解深入子系统,防止带来风险
  • 减少系统依赖,松散耦合(客户端不和子系统直接交流,客户端和外观对象交流,让子系统内部的模块,更容易扩展和维护)
  • 更好的划分访问层次(把需要对外暴露的功能,集中到外观类上,这样既方便客户端调用,也可以很好的隐藏细节)
  • 符合迪米特法则,即最少知道原则,还有依赖倒转原则

缺点

  • 增加子系统、扩展子系统行为容易引人风险
  • 不符合开闭原则

相关设计模式

  • 外观模式和中介者模式
    外观模式关注,外部和子系统之间的交互。中介者模式关注的是子系统之间的交互

  • 外观模式和单例模式
    通常我们把外观模式的外观角色做成单例模式的

  • 外观模式和抽象工厂模式
    外观类可以通过抽象工厂获取子系统实例。这样子系统内部可以对外观类进行屏蔽

代码示例

模拟一个购买商品下单的过程。首先我们有三个子系统,分别是 库存子系统,支付子系统,物流子系统。还有我们外观类。已经客户端代码

  1. 创建子系统
    库存子系统
/**
 * 库存子系统
 */
public class InventoryService {

    /**
     * 校验商品库存是否充足
     */
    public Boolean checkInventory(Goods goods) {
        System.out.println("校验" + goods.getName() + "库存充足");
        return Boolean.TRUE;
    }

    /**
     * 减库存
     */
    public void minusInventory(Goods goods) {
        System.out.println(goods.getName() + "库存减一");
    }
}

支付子系统

/**
 * 支付子系统
 */
public class PayService {

    /**
     * 支付商品
     */
    public Boolean payGoods(Goods goods) {
        System.out.println(goods.getName() + "商品支付成功");
        return Boolean.TRUE;
    }
}

物流子系统

/**
 * 物流子系统
 */
public class LogisticsService {

    /**
     * 商品发货
     * return 物流单号
     */
    public String deliverGoods(Goods goods) {
        System.out.println(goods.getName() + "发货成功");
        return "12345";
    }
}
  1. 创建外观类
    购买服务
/**
 * 外观类-购物
 */
public class ShoppingService {

    private InventoryService inventoryService = new InventoryService();
    private PayService payService = new PayService();
    private LogisticsService logisticsService = new LogisticsService();

    /**
     * 下单
     */
    public void order(Goods goods) {
        if (inventoryService.checkInventory(goods)) {
            //库存校验通过
            if (payService.payGoods(goods)) {
                //支付成功,发物流
                String odd = logisticsService.deliverGoods(goods);
                //减库存
                inventoryService.minusInventory(goods);
                System.out.println("商品购买成功,物流单号:" + odd);
            }
        }
    }
}

  1. 模拟客户端
public class Client {
    public static void main(String[] args) {
        Goods goods = new Goods("篮球");
        ShoppingService shoppingService = new ShoppingService();
        shoppingService.order(goods);
    }
}

执行结果

校验篮球库存充足
篮球商品支付成功
篮球发货成功
篮球库存减一
商品购买成功,物流单号:12345

UML
在这里插入图片描述

使用场景

  1. 在设计初期阶段,应该有意识的将不同的两个层分离,层与层建立外观类
  2. 在开发阶段,子系统因为不断的重构演化,变得越来越复杂,增加外观类可以提供一个简单的接口,减少他们之间的依赖
  3. 在维护一个遗留的大型项目的时,可能这个系统已经难以维护和扩展了,我们可以为新系统开发一个外观类,来提供设计粗糙或高度复杂遗留代码的比较清新简单的接口,让新系统与外观对象交互,外观类与遗留代码交互所有复杂的工作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值