外观模式是一种使用频率很是高,但理解较为简单的设计模式,经过引入一个外观角色来简化客户端与子系统之间的操做,为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度下降,且客户端调用很是方便。java
在大多数状况下,一个网站都会提供一个网站首页。网站首页通常做为整个网站的入口,提供了通往各个子栏目的超连接,用户经过该首页便可进入子栏目获取所需信息。对于用户而言只需记住网站首页网站 URL,而无须记住每一个子栏目的网址。网站首页做为用户访问子栏目的入口,是网站的外观角色。用户经过它能够方便地访问子栏目,固然也能够绕过它直接访问子栏目。
若是没有外观角色,即没有为网站提供一个首页,每一个用户须要记住全部子栏目的 URL,不只会让系统耦合度增长,用户与系统的交互也会异常复杂。编程
外部与一个子系统的通讯必须经过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加易于使用。设计模式
外观模式没有一个通常化的类图描述,这里以类图做为外观模式的描述形式之一。
测试
Facade(外观角色)网站
在客户端能够调用这个角色的方法,在外观角色中能够知道相关子系统的功能和责任;在正常状况下,它将全部从客户端发来的请求委派到相应子系统,传递给相应的子系统对象处理。this
SubSystem(子系统角色)设计
在软件系统中能够同时有一个或多个子系统角色,每个子系统均可以被客户端直接调用,或被外观角色调用,处理外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观仅仅是另一个客户端而言。3d
一个电源总开关能够控制四盏灯、一个风扇、一台空调和一台电视机的启动和关闭。经过该电源总开关能够同时控制全部上述电器设备,使用外观模式设计该系统。
code
子系统类 Light对象
public class Light { private String position; public Light(String position) { this.position = position; } public void on() { System.out.println(this.position + "灯打开"); } public void off() { System.out.println(this.position + "灯打开"); } }
子系统类 Fan
public class Fan { public void on() { System.out.println("风扇打开"); } public void off() { System.out.println("风扇关闭"); } }
子系统类 AirConditioner
public class AirConditioner { public void on() { System.out.println("空调打开"); } public void off() { System.out.println("空调关闭"); } }
子系统类 Televison
public class Television { public void on() { System.out.println("电视机打开"); } public void off() { System.out.println("电视机关闭"); } }
外观类 GeneralSwitchFacade
public class GeneralSwitchFacade { private Light[] lights = new Light[4]; private Fan fan; private AirConditioner ac; private Television tv; public GeneralSwitchFacade() { lights[0] = new Light("左前"); lights[1] = new Light("右前"); lights[2] = new Light("左后"); lights[3] = new Light("右后"); fan = new Fan(); ac = new AirConditioner(); tv = new Television(); } public void on() { lights[0].on(); lights[1].on(); lights[2].on(); lights[3].on(); fan.on(); ac.on(); tv.on(); } public void off() { lights[0].off(); lights[1].off(); lights[2].off(); lights[3].off(); fan.off(); ac.off(); tv.off(); } }
测试类 Client
public class Client { public static void main(String[] args) { GeneralSwitchFacade gsf = new GeneralSwitchFacade(); gsf.on(); System.out.println("-------------"); gsf.off(); } }
运行结果
外观模式优势以下:
外观模式缺点以下:
如下状况可使用外观模式:
为了节约资源,通常将外观类设计为单例类,但这并不意味整个系统只有一个外观类。一个系统中能够设计多个外观类,每一个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能
外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增长应经过修改原有子系统类或增长新的子系统类来实现,不能经过外观类来实现
迪米特法则要求你与直接的朋友通讯。外观模式创造出一个外观对象,将客户端所涉及的属于一个子系统的协做伙伴的数量减到最少。外观类充当了客户类与子系统类之间的第三者,下降了客户类与子系统之间的耦合度。外观模式是实现代码重构以达到迪米特法则要求的一个强有力的武器。
外观模式最大的缺点是违背了开闭原则,当增长新的子系统或移除子系统时需修改外观类,能够经过引入抽象外观类在必定程度上解决该问题,客户端针对抽象外观类编程。对于新的业务需求,不修改原有外观类,对应增长一个新的具体外观类,由新的具体外观类来关联新的子系统对象。