一:外观模式诞生的背景

上图很好的介绍了为什么要有外观模式,从图A中我们可以得知客户想组装一台电脑,他自己需要去电子市场逛卖CPU的公司、卖主板的公司,卖内存条的公司,卖显卡的公司……;但是我们也知道有这么一种公司,替你组装电脑,你只需把自己组装电脑的需求说出来,由装机公司去电子市场逛卖CPU的公司,卖主板的公司,卖内存条的公司,卖显卡的公司……。图B其实就是一个很好的很典型的外观模式的例子。

二:外观模式

外观模式可以很好地解决让子系统外部的客户端在使用子系统的时候,既能简单地使用这些子系统内部的模块,而又不用客户端去与子系统内部的多个模块交互。

1:定义

外观模式又称门面模式,它为子系统中的一组接口提供一个一致的界面Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

界面:主要指从一个组件外部来看这个组件,能够看到什么,这就是这个组件的界面,即外观(这里不是我们想的那么简单的GUI)。

接口:主要是指外部和内部交互的一个通道,通常是指一些方法,可以是类方法,也可以使interface的方法。故这里所说的接口并不是我们想的那么简单的interface。

2:应用外观模式解决问题的思路

仔细分析上面的问题,客户端想要操作更简单点,那么就根据客户端的需要定义一个简单的接口,然后让客户端调用这个接口,剩下的事情客户端就不用管了。

当然了这里所说的接口就是客户端和被访问的系统之间的一个通道,并不一定是指Java的interface。它在外观模式中通常指的是类,这个类被称为外观。

外观模式就是通过引入这么一个外观类,在这个类里面定义客户端想要的简单的方法,然后在这些方法的实现里面,由外观类再去分别调用内部的多个模块来实现功能,从而让客户端变得简单。这样一来,客户端就只需要和外观类交互就可以了。

3:外观模式的结构和说明

Facade:定义子系统的多个模块对外的高层接口,通常需要调用内部的多个模块,从而把客户的请求代理给适当的子系统对象。

模块:接受Facade对象的委派,真正实现功能,各个模块之间有可能交互。但是请注意,Facade对象知道各个模块,但是各个模块不应该知道Facade对象。

三:外观模式代码实现

客户组装电脑的小demo代码:

/*** 主板的模块* @author Peter**/
public interface BoardModuleApi {//卖主板public void sellBoard();
}
public class BoardModuleApiImpl implements BoardModuleApi {public void sellBoard() {System.out.println("主板");}
}
/*** CPU模块接口* @author Peter*/
public interface CPUModuleApi {//卖CPUpublic void sellCPU();
}
public class CPUModuleApiImpl implements CPUModuleApi {public void sellCPU() {System.out.println("CPU");}
}
/*** 显卡模块* @author Peter**/
public interface VideoCardModuleApi {//卖显卡public void sellVideoCard();
}
public class VideoCardModuleApiImpl implements VideoCardModuleApi {public void sellVideoCard() {System.out.println("显卡");}
}
/*** 外观对象* @author Peter*/
public class Facade {//示意方法,满足客户需要的功能public void buy(){//内部实现会调用多个模块BoardModuleApi board = new BoardModuleApiImpl();board.sellBoard();CPUModuleApi cpu = new CPUModuleApiImpl();cpu.sellCPU();VideoCardModuleApi videoCard = new VideoCardModuleApiImpl();videoCard.sellVideoCard();}
}
/*** 客户端* @author Peter**/
public class Client {public static void main(String[] args) {new Facade().buy();}
}

四:外观模式讲解

1:外观模式的目的

外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内多个模块的交互,松散耦合,从而能让外部更简单的使用子系统。

这点要特别注意,因为外观是当做子系统对外的接口出现的,虽然也可以定义一些子系统没有的功能,但是不建议这么做。外观应该是包装已有的功能,它主要负责组合已有功能来实现客户需要,而不是添加新的实现。

2:使用外观模式和不使用外观模式的区别

最明显的区别就是原来在客户端进行功能组装的代码现在是在Facade里面实现。Facade实现系统的这边,那么它就相当于屏蔽了外部客户端和系统内部模块的直接交互,从而把A、 B、 C模块组合成为一个整体对外,不但方便了客户端的调用,而且封装了系统内部的细节功能。即Facade与各个模块交互的过程已经是内部实现了。这样一来,如果今后调用模块的算法发生了变化,比如变化成要先调用B,然后调用A,那么只需要修改Facade的实现就可以了。

另一个好处是Facade的功能可以被很多个客户端调用,即Facade可以实现功能的共享,即实现复用。同样的调用代码就只用在Facade里面写一次就好了,而不用在多个调用的地方重复写。

还有一个潜在好处,对使用Facade的人员来说,Facade大大节省了他们的学习成本,他们不需要了解A、B、C的实现,也不需要和它们进行交互,只需要了解Facade即可,学习简单,使用简单,开发简单。

3:有外观但是也可以不使用

虽然有Facade,但是如果有需要,外部还是可以绕过Facade,从而直接调用某个模块的接口,这样就能实现兼顾组合功能和细节功能。

4:外观提供了缺省的实现功能

外观对象可以为用户提供一个简单的、缺省的实现,这个实现对大多数的用户来说都是已经足够了的。但是外观并不限制哪些需要更多定制功能的用户,可以直接越过外观去访问内部模块的功能。

5:外观模式调用顺序示意图

五:外观模式的实现

1:Facade的实现

对于一个子系统而言,外观类不需要很多,通常可以实现成为一个单例。也可以直接把外观中的方法实现成为静态方法,这样就不需要创建外观对象的实例而直接调用,这种实现就相当于把外观类当成一个辅助工具类实现。

public interface AModuleApi {public void testA();
}
public class AModuleImpl implements AModuleApi {public void testA() {System.out.println("A Module.");}
}
public interface BModuleApi {public void testB();
}
public class BMoudleImpl implements BModuleApi {public void testB() {System.out.println("B Module.");}
}
public interface CModuleApi {public void testC();
}
public class CModuleImpl implements CModuleApi {public void testC() {System.out.println("C Module");}
}
public class Facade {private Facade(){}public static void test(){ //实现成为静态方法AModuleApi a = new AModuleImpl();a.testA(); BModuleApi b = new BMoudleImpl();b.testB();    CModuleApi c = new CModuleImpl();c.testC();}
}
public class Client {public static void main(String[] args) {Facade.test();}
}

2:Facade可以实现成为interface。

缺点:增加了系统的复杂度,因为这样会需要一个对Facade的实现,还需要一个来获取Facade接口对象的工厂。

优点:Facade实现成为接口,还附带一个功能,能够有选择性的暴露接口的方法,尽量减少模块对子系统外提供接口方法。

即:一个模块的接口中定义的方法可以分成两部分,一部分是给子系统外部使用的,一部分是子系统内部的模块间相互调用时使用的。有了Facade接口,那么用于子系统内部的接口功能就不用暴露给子系统的外部了。

public interface AModuleApi {//子系统外部使用public void testA1();//子系统内部使用public void testA2();//子系统内部使用public void testA3();
}
public class AModuleImpl implements AModuleApi {public void testA1() {System.out.println("A1 Module");}public void testA2() {System.out.println("A2 Module");}public void testA3() {System.out.println("A3 Module");}
}
public interface BModuleApi {//子系统外部使用public void testB1();//子系统内部使用public void testB2();//子系统内部使用public void testB3();
}
public class BMoudleImpl implements BModuleApi {public void testB1() {System.out.println("B1 Module");}public void testB2() {System.out.println("B2 Module");}public void testB3() {System.out.println("B3 Module");}
}
public interface CModuleApi {//子系统外部使用public void testC1();//子系统内部使用public void testC2();//子系统内部使用public void testC3();
}
public class CModuleImpl implements CModuleApi {public void testC1() {System.out.println("C1 Module");}public void testC2() {System.out.println("C2 Module");}public void testC3() {System.out.println("C3 Module");}
}
public interface FacadeApi {public void testA1();public void testB1();public void testC1();public void test();
}
public class Facade implements FacadeApi {public void testA1() {AModuleApi a = new AModuleImpl();a.testA1();}public void testB1() {BModuleApi b = new BMoudleImpl();b.testB1();}public void testC1() {CModuleApi c = new CModuleImpl();c.testC1();}public void test() {testA1();testB1();testC1();        }
}
public class Client {public static void main(String[] args) {new Facade().test();}
}

3:Facade方法的实现

Facade方法实现中,一般是负责把客户端的请求转发给子系统内部的各个模块进行处理,Facade方法本身并不进行功能的处理,Facade的方法实现只是实现一个功能的组合调用。

当然在Facade实现一个逻辑处理也并不是不可以,但是不建议这样做,因为这不是Facade的本意,也超出了Facade的边界。

六:外观模式的优缺点

1:外观模式的优点

(1)松散耦合(外观模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护);

(2)简单易用(外观模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟外观交互就可以了,相当于外观类为外部客户端使用子系统提供了一站式服务)

(3)更好地划分访问的层次(通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观中,这样既方便客户端使用,也很好地隐藏了内部的细节)

2:外观模式的缺点

过多的或者是不太合理的Facade也容易让人迷惑。到底是调用Facade还是直接调用模块,这是一个艰难的choice。

七:小思外观模式

外观模式的本质是:封装交互,简化调用。

外观模式体现了“最少知识原则”。

在希望为一个复杂子系统提供一个简单接口的时候可以考虑使用外观模式,使用外观对象来实现大部分客户需要的功能,从而简化客户的使用;

想要让客户程序和抽象类的实现部分松散耦合可以考虑使用外观模式,使用外观对象来将这个子系统与它的客户分离开,从而提高子系统的独立性和可移植性;

如果构建多层结构的系统,可以考虑使用外观模式,使用外观对象作为每层的入口,简化层间调用,松散层次之间的依赖关系。

外观模式(Java)相关推荐

  1. Java设计模式之结构型:外观模式

    一.什么是外观模式: 外观模式通过对客户端提供一个统一的接口,用于访问子系统中的一群接口.使用外观模式有以下几点好处: (1)更加易用:使得子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要 ...

  2. java计数器策略模式_策略模式与外观模式 | 学步园

    1.策略 :定义不同的 2. 例子:随机生成宠物,并统计各种宠物生成数量. a) 抽象类:PetCreator,用于随机生成宠物. package context; import java.util. ...

  3. Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

    Java设计模式Ⅳ 1.装饰者模式 1.1 装饰者模式概述 1.2 代码理解 2.组合模式 2.1 组合模式概述 2.2 代码理解 3.外观模式 3.1 外观模式概述 3.2 代码理解 4.享元模式 ...

  4. java外观设计修改_Java设计模式之外观模式和装饰器模式的设计(精选)

    前言 本篇来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接 ...

  5. java设计模式之九外观模式(Facade)

    外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口 ...

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

    概述 今天要说的外观模式是一个相对简单的设计模式,而且在日常的开发中,可能你也会时常使用它,只是你可能并未想过这是一个设计模式.本文会从一些实例着手,来对本文要说明的外观模式进行尽可能全面的讲解.希望 ...

  7. Java设计模式-外观模式

    我又来了,继Java设计模式之桥接模式后,现在来到了外观模式啦,外观模式又称为门面模式啦

  8. Java设计模式学习总结(12)——结构型模式之外观模式

    外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及 ...

  9. java 外观模式_Java设计模式11:外观模式

    外观模式 外观模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的外观对象进行.外观模式是一个高层次的接口,使得子系统更易于使用. 医院的例子 现代的软件系统都是比较复杂的.假如把医院比作一 ...

  10. 【Java设计模式】简单学外观模式——万能遥控器

    目录 说明 目标 实现方式 注意事项 其他链接 说明 结构型模式之一,其他还有适配器模式.桥接模式.组合模式.装饰模式.享元模式.代理模式 外观模式(Facade Pattern)通过定义一个一致的接 ...

最新文章

  1. 机器学习的第一个难点,是数据探索性分析
  2. 人工智能如何彻底改变全球物流和供应链管理
  3. 06. 用css实现三角形
  4. 太阳能发电产业有望大发展
  5. 【知识星球】Attention网络结构上新,聚焦才能赢
  6. 《数据安全法》今日实施,中国信通院联合百度等企业发起“数据安全推进计划”
  7. 漫画 | 如何凭实力炒老板鱿鱼,并喜提N+1~
  8. Win7下如何用Eclipse导出jar类型的文件,并且可以用鼠标双击打开jar类型的文件的方法(解决双击后一闪而过)...
  9. java 如何导出json文件_java导出json格式文件的示例代码
  10. Katalon Recorder录制脚本
  11. 用maven搭建多模块项目
  12. linux scp命令_太麻烦!使用 Linux scp 命令下载文件到 Windows 桌面
  13. scjp考试准备 - 11 - 类型转换2
  14. 修改Firebug字体
  15. web api authentication
  16. 全国首个NB-IoT规模化商用 - BC95模块
  17. Scratch之猫和老鼠
  18. js字符串分割split()
  19. wpsppt怎样让图片模糊_PPT怎么设置图片由模糊到清楚?
  20. 干货 | 携程用户数据采集与分析系统

热门文章

  1. 差分方程组 matlab,差分方程组的迭代
  2. Android 通过samples\android-x\BluetoothChat学习蓝牙操作
  3. Spark Tungsten
  4. rn开发板那些事之开发环境与开发板配置
  5. unity 声音AudioSystem(二)
  6. 炎炎夏日!东南亚LazadaShopee泳衣品类热销榜单来袭
  7. 应用安全系列之三十四:数值溢出
  8. the thought
  9. linux cd 命令详解,linux cd 命令详解
  10. OpenSSL - 学习/实践