一. 定义与类型

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

类型:结构性

二. 使用场景

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

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

三. 优缺点

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

减少系统依赖,松散耦合

更好的划分访问层次

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

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

   不符合开闭原则

四. 相关设计模式

外观模式和中介者模式

外观模式和单例模式

外观模式和抽象工厂模式

五. 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 设计模式泛谈&装饰者模式和单例模式

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

  4. Java设计模式之接口型模式总结

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6508967.html 之前认真学习了Java设计模式中的四大接口型模式,分别为:适 ...

  5. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  6. java设计模式之Proxy(代理模式)

    java设计模式之Proxy(代理模式) 2008-03-25 20:30 227人阅读 评论(0) 收藏 举报 设计模式javaauthorizationpermissionsstringclass ...

  7. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  8. Java设计模式系列-工厂方法模式

    原创文章,转载请标注出处:<Java设计模式系列-工厂方法模式> 一.概述 工厂,就是生产产品的地方. 在Java设计模式中使用工厂的概念,那就是生成对象的地方了. 本来直接就能创建的对象 ...

  9. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  10. 折腾Java设计模式之中介者模式

    博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并 ...

随机推荐

  1. 事务日志已满,原因为“ACTIVE_TRANSACTION”

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 异常处理汇总-数据库系列  http://www.cnblogs.com/dunitia ...

  2. CSS实现水平|垂直居中漫谈

    利用CSS进行元素的水平居中,比较简单,手到擒来:行级元素设置其父元素的text-align center,块级元素设置其本身的left 和 right margins为auto即可.而撸起垂直居中, ...

  3. 简单的百度贴吧爬虫实现(urllib)

    环境:ubuntu 16.04 LTS   (X86-64),pycharm python版本 :3.5.1+ #生成的文件默认会保存到代码所在根目录 1 import urllib.request, ...

  4. HDU 1907

    博弈入门题吧. 把尼姆博弈推广到n堆,都是用异或运算.还有个总结的地方是,只要先手面对的是奇异局势,则胜负都掌握在后手.本题,题目要求是最后拿完的输,尼姆博弈是最后拿完的赢.但实际上优先权都掌握在后手 ...

  5. max取得数组的最大值

    var arr = [1,2,3,4,5,2,2,4,52,5,6,5,4,4]; var maxNum = Math.max.apply(Math,arr); var maxIndex = arr. ...

  6. oracle空表导不出来

    在oracle 11g r2中,使用exp有时候会导不出空的表,原因是这些表没有分配空间,手工分配空间即可导出. ----查询当前用户下的所有空表: select table_name from us ...

  7. 关于windows系统无法更新的解决方法

    操作系统无法更新解决方案! 1.检查网络连接是否正常: 2.检查控制面板设置,windows更新是否开启: 3.检查计算机-管理-服务和应用程序-服务组件里的windows update是否开启: 4 ...

  8. ajax工作原理及jsonp跨域详解

    一.Ajax简介 ajax = 异步 JavaScript 和 XML. ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术.我们知道,传统的网页(不使用ajax)如果需要更新内容, ...

  9. python使用数组作为索引遍历数组

    python使用数组作为索引遍历数组 觉得有用的话,欢迎一起讨论相互学习~Follow Me python使用数组作为索引遍历数组 import numpy as np a=np.arange(0,5 ...

  10. linux shell脚本编程笔记(四): 获取字符串长度的七种方法

    获取字符串长度的七种方法 1. \${#str} 2.awk的length 备注:1) 最好用{}来放置变量2) 也可以用length($0)来统计文件中每行的长度 3.awk的NF 备注: -F为分 ...