设计模式之外观模式

定义

提供一个高层次的接口,使得子系统更易于使用

使用场景

当你的程序有很多个模块,或者说子系统。你希望给用户提供一个统一的操作界面类,而不是让用户分别与这些模块交互。

一种设计是:给用户提供一套面板方用来法完成一般性的功能,如果面板提供的方法不能满足用户需求,用户还可以直接使用具体模块的功能来达到自己的目的。
另一种设计是:用户完全看不到各子模块,所有操作必须通过面板来完成,如果面板没有提供相应的功能,那也就gg了。

如何使用

1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。

应用实例:

  1. 去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
  2. JAVA 的三层开发模式。

优点:

1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。

缺点:

不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。

uml 类图

在这里插入图片描述

角色

  • Facade(外观)角色:提供一个外观接口,对外,它提供一个易于客户端访问的接口,对内,它可以访问子系统中的所有功能。
  • SubSystem(子系统)角色:子系统在整个系统中可以是一个或多个模块,每个模块都有若干类组成,这些类可能相互之间有着比较复杂的关系。

实例

公司最近突然对正在开发的商城项目感了兴趣,所以要求出各种各样的报表。,因为公司要求的报表数据来自不同的子系统,这些子系统相互之间还有依赖,要想获得一份完整的报表,需要访问好多个模块

第一步,确定需要调用的子模块

确定我们要使用面板隐藏的子模块,此处假设有3个子模块

//订单系统
public class OrderSys {
    public String getOrderNum(){
        System.out.println("获取订单号");
        return "123456";
    }
}
//支付系统
public class PaymentSys {
    private OrderSys orderSys;
    public PaymentSys(OrderSys orderSys) {
        this.orderSys = orderSys;
    }
    public BigDecimal getOrderAccount(String orderNum){
        System.out.println(String.format("获取%s订单支付金额",orderNum));
        return BigDecimal.valueOf(500);
    }
}
//物流系统
public class DeliverySys {
    public int getDeliveryTime(){
        System.out.println("获取配送耗时");
        return 30*60;//30分钟
    }
}

第二步,创建外观类

这个模式实在是太简单了,基本没什么可说的。这个外观类就是引用其他功能模块,完成相关的功能对外暴露操作接口。

例如本例中的外观类ReportFacade使用了OrderSys 、PaymentSys与 DeliverySys 3个子模块来完成一个生成报表的功能,客户端只需要通过此方法就可以生成报表了,不用关心那些子模块。

public class ReportFacade {
    private OrderSys orderSys ;
    private PaymentSys paymentSys;
    private DeliverySys deliverySys;

    public ReportFacade(OrderSys orderSys, PaymentSys paymentSys, DeliverySys deliverySys) {
        this.orderSys = orderSys;
        this.paymentSys = paymentSys;
        this.deliverySys = deliverySys;
    }
    public void generateReport() {
        final String orderNum = orderSys.getOrderNum();
        System.out.println(String.format("\n报表\n--------------------------------------------\n" +
                        "订单号:%s | 金额:%s元 | 配送耗时:%s分钟",
                orderNum,
                paymentSys.getOrderAccount(orderNum).toPlainString(),
                String.valueOf(deliverySys.getDeliveryTime() / 60))
        );
    }
}

第三步,客户端使用

public class FacadeClient {
    public static void main(String[] args) {

        OrderSys orderSys = new OrderSys();
        PaymentSys paymentSys = new PaymentSys(orderSys);
        DeliverySys deliverySys = new DeliverySys();
        new ReportFacade(orderSys, paymentSys, deliverySys).generateReport();

    }
}

输出

获取订单号
获取158952578订单支付金额
获取配送耗时

报表
--------------------------------------------
订单号:158952578 | 金额:2550| 配送耗时:12分钟

可见客户端只于外观类交互,完全不用与具体的子模块交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶一菩提魁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值