一. 定义与类型

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

类型:结构性

二. 使用场景

子系统越来越复杂,增加外观模式提供简单调用接口

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

三. 优缺点

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

减少系统依赖,松散耦合

更好的划分访问层次

符合迪米特法则,即最少知道原则

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

   不符合开闭原则

四. 相关设计模式

外观模式和中介者模式

外观模式和单例模式

外观模式和抽象工厂模式

五. Coding

假设一个场景,在商城中用积分退换商品时,有几个步骤:

(1) 校验:判断当前积分是否能够兑换商品

(2) 支付:使用积分支付兑换商品

(3)物流:将兑换的商品,送到目的地

在实际的场景中,一般正常的步骤是,用户直接用积分兑换商品,并没有校验,支付,物流等细节。而是提供了一个统一的兑换接口,来访问这些子系统。

/**
* @program: designModel
* @description: 积分礼物
* @author: YuKai Fan
* @create: 2018-12-17 10:11
**/
public class PointsGift {
private String name; public PointsGift(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
/**
* @program: designModel
* @description: 校验系统
* @author: YuKai Fan
* @create: 2018-12-17 10:12
**/
public class QualifyService {
public boolean isAvailable(PointsGift pointsGift) {
System.out.println("校验" + pointsGift.getName() + " 积分资格通过,库存通过");
return true;
}
}
/**
* @program: designModel
* @description: 校验系统
* @author: YuKai Fan
* @create: 2018-12-17 10:12
**/
public class QualifyService {
public boolean isAvailable(PointsGift pointsGift) {
System.out.println("校验" + pointsGift.getName() + " 积分资格通过,库存通过");
return true;
}
}
/**
* @program: designModel
* @description: 积分支付系统
* @author: YuKai Fan
* @create: 2018-12-17 10:13
**/
public class PoingtsPaymentService {
public boolean pay(PointsGift pointsGift) {
//扣减积分
System.out.println("支付" + pointsGift.getName() + " 积分成功");
return true;
}
}
/**
* @program: designModel
* @description: 物流系统
* @author: YuKai Fan
* @create: 2018-12-17 10:15
**/
public class ShippingService {
public String shipGift(PointsGift pointsGift) {
//物流系统的对接逻辑
System.out.println(pointsGift.getName() + "进入物流系统");
String shippingOrderNo = "666";
return shippingOrderNo;
}
}

统一对外开放的接口

/**
* @program: designModel
* @description: 礼物兑换
* @author: YuKai Fan
* @create: 2018-12-17 10:17
**/
public class GiftExchangeService {
private QualifyService qualifyService;
private PoingtsPaymentService poingtsPaymentService ;
private ShippingService shippingService; public void giftExchange(PointsGift pointsGift) {
if (qualifyService.isAvailable(pointsGift)) {
//资格校验通过
if (poingtsPaymentService.pay(pointsGift)) {
//如果支付积分成功
String shippingOrderNo = shippingService.shipGift(pointsGift);
System.out.println("物流系统下班成功,订单号:" + shippingOrderNo);
}
}
} public QualifyService getQualifyService() {
return qualifyService;
} public void setQualifyService(QualifyService qualifyService) {
this.qualifyService = qualifyService;
} public PoingtsPaymentService getPoingtsPaymentService() {
return poingtsPaymentService;
} public void setPoingtsPaymentService(PoingtsPaymentService poingtsPaymentService) {
this.poingtsPaymentService = poingtsPaymentService;
} public ShippingService getShippingService() {
return shippingService;
} public void setShippingService(ShippingService shippingService) {
this.shippingService = shippingService;
}
}

客户端:

/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-12-17 10:21
**/
public class Test {
public static void main(String[] args) {
PointsGift pointsGift = new PointsGift("T shirt");
GiftExchangeService giftExchangeService = new GiftExchangeService(); giftExchangeService.setQualifyService(new QualifyService());
giftExchangeService.setPoingtsPaymentService(new PoingtsPaymentService());
giftExchangeService.setShippingService(new ShippingService()); giftExchangeService.giftExchange(pointsGift);
}
}

UML类图:

看上面的UML类图,应用层与子系统依旧存在着联系,这是因为没有集成spring的依赖注入的原因,而是直接在应用层中创建了子系统的对象注入到外观对象中。

进一步完善后的代码:

/**
* @program: designModel
* @description: 礼物兑换
* @author: YuKai Fan
* @create: 2018-12-17 10:17
**/
public class GiftExchangeService {
private QualifyService qualifyService = new QualifyService();
private PoingtsPaymentService poingtsPaymentService = new PoingtsPaymentService();
private ShippingService shippingService = new ShippingService(); public void giftExchange(PointsGift pointsGift) {
if (qualifyService.isAvailable(pointsGift)) {
//资格校验通过
if (poingtsPaymentService.pay(pointsGift)) {
//如果支付积分成功
String shippingOrderNo = shippingService.shipGift(pointsGift);
System.out.println("物流系统下班成功,订单号:" + shippingOrderNo);
}
}
} public QualifyService getQualifyService() {
return qualifyService;
} public void setQualifyService(QualifyService qualifyService) {
this.qualifyService = qualifyService;
} public PoingtsPaymentService getPoingtsPaymentService() {
return poingtsPaymentService;
} public void setPoingtsPaymentService(PoingtsPaymentService poingtsPaymentService) {
this.poingtsPaymentService = poingtsPaymentService;
} public ShippingService getShippingService() {
return shippingService;
} public void setShippingService(ShippingService shippingService) {
this.shippingService = shippingService;
}
}
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-12-17 10:21
**/
public class Test {
public static void main(String[] args) {
PointsGift pointsGift = new PointsGift("T shirt");
GiftExchangeService giftExchangeService = new GiftExchangeService(); // giftExchangeService.setQualifyService(new QualifyService());
// giftExchangeService.setPoingtsPaymentService(new PoingtsPaymentService());
// giftExchangeService.setShippingService(new ShippingService()); giftExchangeService.giftExchange(pointsGift);
}
}

UML类图:

上面的新类图,才是真正的外观模式的结构类图,支持了迪米特法则。

在开发过程中,要注意应用层到底有没有与子系统发生关系,要是又有了一个新的子系统,那就不符合开闭原则了。如果这个系统以后不需要扩展,或者扩展的子系统非常有限,那就用实体外观类就可以了,可以减少复杂度。但是如果需要经常新加子系统,那就需要使用抽象外观类。

六. 源码分析

springjdbc中的closeConnection(),closeStatement(),closeResultSet()等方法

mybatis中的Configuration配置类,使用的也是外观模式思想

tomcat源码中RequestFacade是一个request的一个外观类,实现了HttpServletRequest接口,

  还有一个Request类也实现了HttpServletRequest接口,在request里声明了RequestFacade对象,而且具体的操作都是用的这个对象

  tomcat源码中大量的使用了外观类

java设计模式——外观模式(门面模式)的更多相关文章

  1. 外观模式 门面模式 Facade 结构型 设计模式(十三)

    外观模式(FACADE) 又称为门面模式   意图 为子系统中的一组接口提供一个一致的界面 Facade模式定义了一个高层接口,这一接口使得这一子系统更加易于使用. 意图解析 随着项目的持续发展,系统 ...

  2. Java设计模式——外观模式

    JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  3. 【设计模式】Java设计模式 - 外观模式

    Java设计模式 - 外观模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  4. 设计模式在实际业务应用中的介绍之3——外观或门面模式Facade对AOP装配业务工厂的应用

    在C#中实现的基于外观或门面模式打造的业务应用案例 以前一直没有想过写一些东西来把项目中用到的知识点及技术实现做一个归纳整理并分享出来.现在打算逐渐的把项目中的一些东西整理并分享出来,与大家共勉! 外 ...

  5. 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...

  6. 重学 Java 设计模式:实战迭代器模式「模拟公司组织架构树结构关系,深度迭代遍历人员信息输出场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 相信相信的力量! 从懵懂的少年,到拿起键盘,可以写一个Hell ...

  7. 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 实现不了是研发的借口? 实现不了,有时候是功能复杂度较高难以实 ...

  8. 重学 Java 设计模式:实战状态模式「模拟系统营销活动,状态流程审核发布上线场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! @ 目录 一.前言 二.开发环境 三.状态模式介绍 四.案例场景模拟 1 ...

  9. 重学 Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 能力,是你前行的最大保障 年龄会不断的增长,但是什么才能让你不 ...

  10. Java 设计模式泛谈&装饰者模式和单例模式

    设计模式(Design Pattern) 1.是一套被反复使用.多人知晓的,经过分类编目 的 代码设计经验总结.使用设计模式是为了可重用代码,让代码更容易维护以及扩展. 2.简单的讲:所谓模式就是得到 ...

随机推荐

  1. 移动测试之appium+python 入门代码(二)

    ps: 对于环境安装可能会碰到各种问题,还是要一一解决. 执行: appium-doctor 显示上边界面说明,环境已完成. 同时将手机连接主机(用数据线) ^_^ 执行 adb devices 显示 ...

  2. DexClassLoader和PathClassLoader

    Android的ClassLoader体系 在Android中可以跟java一样实现动态加载jar,但是Android使用Dalvik VM,不能直接加载java打包jar的byte code,需要通 ...

  3. Linux环境编程--waitpid与fork与execlp

    waitpid waitpid(等待子进程中断或结束) 表头文件 #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t w ...

  4. pyplot

    错误: 执行 import matplotlib.pyplot 报错 ImportError: No module named _tkinter, please install the python- ...

  5. 摄像机模型 (Camera Model)

    摄像机通过成像透镜将三维场景投影到摄像机二维像平面上,这个投影可用成像变换描述,即摄像机成像模型.摄像机成像模型有不同描述方式,本节首先介绍机器视觉中的常用坐标系,然后介绍摄像机的线性模型和非线性模型 ...

  6. Ubuntu瞎胡搞

    ubutnu的几个必不可少的软件: 1.Guake,超级方便的终端 2.Unity tweak tool 3.VLC,本地视频播放器 4.MyPint,简单画图软件 5.GIMP,PS工具 Subli ...

  7. Powershell(2)

    powershell(2) 帮助系统(显示出来的参数语法要比Unix中help复杂) save-help -destinationpath c:\help update-help -force -so ...

  8. 【安全测试】sql注入

    SQL注入攻击是黑客对 数据库 进行攻击的常用手段之一,随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员越来越多,但是由于程序员水平及经验页参差不齐,相当大部分程序员在编写代码的时候没有 ...

  9. .NET面试题3

    1.什么是拆箱和装箱? 2.什么是箱子? 3.箱子放在哪里? 4.装箱和拆箱有什么性能影响? 5.如何避免隐身装箱? 6.箱子的基本结构? 7.装箱的过程? 8.拆箱的过程? 9.下面这段代码输出什么 ...

  10. vue学习中遇到的onchange、push、splice、forEach方法使用

    最近在做vue的练习,发现有些js中的基础知识掌握的不牢,记录一下: 1.onchange事件:是在域的内容改变时发生,单选框与复选框改变后触发的事件. 2.push方法:向数组的末尾添加一个或多个元 ...