前言

这次要介绍的是外观模式(也称为门面模式),外观模式也属于结构型模式,其实外观模式还是非常好理解的,简单的来讲就是将多个复杂的业务封装成一个方法,在调用此方法时可以不必关系具体执行了哪些业务,而只关心结果即可。这个场景其实在日常开发中使用的频率还是非常高的,下面来简单了解一下吧。

外观模式

概念介绍

外观模式是隐藏了系统的复杂性,能够为子系统中的一组接口提供一个统一的接口。客户在使用系统时不必和子系统打交道了,降低了客户和子系统间的耦合。

举例

喝茶问题,当纪大烟袋和二想喝茶了,这个时候他们就会自己动手,拿茶具,开水,茶叶然后就把茶泡了。过程如下图。

这样两个人都要自己操作茶具,开水,茶叶等,但是其实他俩就是想喝茶,才不关心茶是怎么泡出来的。所以这个时候他们俩就去茶馆了,这样也不用自己动手泡茶了,直接告诉茶馆的店小二儿就行了。此时过程就变成了下面这样的了。

下面用代码来实现一下这个过程:

先获得饮用水

public class DrinkableWater {

    public DrinkableWater(){
System.out.println("可饮用水准备好了");
} //煮水
public void facadeWater(){
System.out.println("可饮用水沸腾了");
}
}

再获得茶叶

public class Tea {

    public Tea(){
System.out.println("茶叶准备好了。");
} //取茶
public void facadeTea(){
System.out.println("可以泡茶了。");
} }

然后获得茶杯就可以泡茶了。

public class TeaCup {

    public TeaCup(){
System.out.println("茶杯准备好了");
} //泡茶
public void facadeTeaCup(Tea tea){ tea.facadeTea();
System.out.println("茶叶泡进茶杯了。");
System.out.println("等了一会儿,一杯又香又浓的茶冲好了。");
}
}

店小二泡茶

public class Waiter {

    private DrinkableWater drinkableWater = new DrinkableWater();
private TeaCup teaCup = new TeaCup();
private Tea tea = new Tea(); //获得一杯茶
public void getTea(){ drinkableWater.facadeWater();
teaCup.facadeTeaCup(tea); } }

顾客来喝茶了

public class Customer {

    public static void main(String[] args) {

        //叫店小二
Waiter waiter = new Waiter();
//从店小二那获得一杯茶
waiter.getTea(); } }

运行结果

可饮用水准备好了
茶杯准备好了
茶叶准备好了。
可饮用水沸腾了
可以泡茶了。
茶叶泡进茶杯了。
等了一会儿,一杯又香又浓的茶冲好了。

外观模式的分析

外观模式的抽象结构图如下:

在外观模式中主要包含如下几个角色。

1、门面角色(facade):这是外观模式的核心。它被客户角色调用,因此它熟悉子系统的功能。它内部根据客户角色已有的需求预定了几种功能组合。

2、子系统角色(SystemA、SystemB、SystemC):实现了子系统的功能。对子系统角色来说,facade角色与客户角色一样,是未知的,它没有任何facade角色的信息和链接。

3、客户角色(client):调用facade角色来完成要得到的功能。

在上面的泡茶的例子中,和二和纪大烟袋就是客户角色,茶馆店小二儿就是门面角色,茶具、饮用水、茶叶就是子系统角色。

外观模式的优点

1、对客户端屏蔽了子系统组件,减少了客户端处理的对象数量,也减少了客户端的代码量。

2、实现了客户端和子系统的松散耦合,使得子系统个变化不会影响到调用它的客户端,只需要改变外观类即可。

3、一个子系统的变化不会影响到另一个子系统,子系统内部变化也不会影响到外观对象。

外观模式的缺点

1、不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性。

2、如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则。

适用场景

当要为访问一系列复杂的子系统提供一个简单入口时可以使用外观模式。

客户端程序与多个子系统之间存在很大的依赖性。引入外观类可以将子系统与客户端解耦,从而提高子系统的独立性和可移植性。

在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

延伸

在上面的例子中,我们定义的门面是一个具体的类,但是当需要增加新的功能的时候,就需要修改门面类了,所以最好的办法是做成抽象门面,也就是将门面类的功能抽象出来,然后又不同的需求的时候,可以做两个具体的门面类。例如:纪大烟袋和二去茶馆喝茶是一个门面类,去上街买东西又是另一个门面类。

想了解更多的设计模式请查看Java设计模式学习记录-GoF设计模式概述

我不慌,世界就不慌。加油吧!

Java设计模式学习记录-外观模式的更多相关文章

  1. Java设计模式学习记录-模板方法模式

    前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...

  2. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  3. Java设计模式学习记录-备忘录模式

    前言 这次要介绍的是备忘录模式,也是行为模式的一种 .现在人们的智能手机上都会有备忘录这样一个功能,大家也都会用,就是为了记住某件事情,防止以后自己忘记了.那么备忘录模式又是什么样子的呢?是不是和手机 ...

  4. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

  5. Java设计模式学习记录-解释器模式

    前言 这次介绍另一个行为模式,解释器模式,都说解释器模式用的少,其实只是我们在日常的开发中用的少,但是一些开源框架中还是能见到它的影子,例如:spring的spEL表达式在解析时就用到了解释器模式,以 ...

  6. Java设计模式学习记录-命令模式

    前言 这次要介绍的是命令模式,这也是一种行为型模式.最近反正没有面试机会我就写博客呗,该投的简历都投了.然后就继续看书,其实看书也会给自己带来成就感,原来以前不明白的东西,书上已经给彻底的介绍清楚了, ...

  7. Java设计模式学习记录-桥接模式

    前言 这次介绍结构型设计模式中的第二种模式,桥接模式. 使用桥接模式的目的就是为了解耦,松散的耦合更利于扩展,但是会增加相应的代码量和设计难度. 桥接模式 桥接模式是为了将抽象化与实现化解耦,让二者可 ...

  8. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  9. Java设计模式学习记录-建造者模式

    前言 今天周末,有小雨,正好也不用出门了,那就在家学习吧,经过了两周的面试,拿到了几个offer,但是都不是自己很想去的那种,要么就是几个人的初创小公司,要么就是开发企业内部系统的这种传统开发,感觉这 ...

随机推荐

  1. 让.net core 支持静态文件

    想不到默认的.net core竟然不支持静态文件,还需要额外配置中间件来支持 1.Nuget安装  Microsoft.aspnetcore.staticfiles 2.在Startup.cs中使用服 ...

  2. flex布局之flex-basis采坑

    场景: 容器设置为display: flex,容器里的子项目部分设置 flex: auto,子项目的宽高自适应正常,但如果再往子项目里嵌套一个(如:div),并设置高度(如:height: 100%) ...

  3. js--sort()排序方法的使用--(笔记)

    情况1: var arr = [ 'c', 'd', 'a', 'e' ];      //都是字母的情况arr.sort();//alert( arr );                     ...

  4. C语言编程常见技巧(问题???)

    本文章根据<算法竞赛入门经典(第二版)>一书整理... 第一章 程序设计入门 printf 语句控制输出小数位数或总长度 printf("%.3f\n",8.0/5.0 ...

  5. qhfl-7 结算中心

    结算中心,即从购物车前往支付前的确认页面,这里要开始选择优惠券了 """ 前端传过来数据 course_list 课程列表 redis 中将要存放的结算数据 { sett ...

  6. 第35章:MongoDB-集群--Master Slave(主从复制)

    ①主从复制 最基本的设置方式就是建立一个主节点和一个或多个从节点,每个从节点要知道主节点的地址.采用双机备份后主节点挂掉了后从节点可以接替主机继续服务,所以这种模式比单节点的高可用性要好很多. ②注意 ...

  7. [solution] JZOJ-5458 质数

    [solution] JZOJ-5458 质数 题面 Description 小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小X 认为,质数是一切自然数起源的地方. 在小X ...

  8. 基于UML的毕业选题系统建模研究

    一.基本信息 标题:基于UML的毕业选题系统建模研究 时间:2018 出版源:电脑迷 领域分类:UML建模技术 二.研究背景 问题定义:为了加强学生设计分析开发软件的相关能力,有效避免结构化模型存在的 ...

  9. @WebFilter怎么控制多个filter的执行顺序

    转自:http://blog.csdn.net/liming_0820/article/details/53332070 之前我们控制多个filter的执行顺序是通过web.xml中控制filter的 ...

  10. (转)web前端知识精简

    Web前端技术由 html.css 和 javascript 三大部分构成,是一个庞大而复杂的技术体系,其复杂程度不低于任何一门后端语言.而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学 ...