Java设计模式(13)-外观模式
在现实生活中有很多这样的例子,比如,炒股,散户股民大多对股票金融知识缺乏,所以他们想要炒股赚钱往往看运气,但是散户想要保证低风险的投资和拿到稳定回报,怎么办呢?大多数人会选择购买基金,相对于股票,散户们不需要专业知识,只需要将自己交给基金会,由专业人士替他们购买股票,赚到钱后再按资金比例分给他们,这样就大大降低了投资风险。 Figure 1. 股票与基金示意图 基金作为一个中间对象,它解决了股民专业知识匮乏却也能投资股票赚钱的需求。其实,这就是外观模式。 1. 外观模式简介 外观模式(Facade Pattern),也叫门面模式,是一种经常被使用的结构性设计模式。DP对其定义如下:通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问。 还记得 迪米特法则] 吗? 迪米特法则(Law of Demeter,LoD),又叫作最少知识原则(Least Knowledge Principle,LKP),描述了如何设计对象之间的依赖关系,它的定义如下:一个对象对自己所依赖的对象知道的越少越好。更进一步的意思,即:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。 外观模式严格体现了迪米特法则,它降低了系统之间的耦合性和复杂度,提高了系统的可维护性。 外观模式有三种角色: 外观(Facade)角色:整合多个子系统,为其提供统一的接口实以现业务需求; 子系统(SubSystem)角色: 实现某方面的业务功能,供外观角色调用,但是并不知道外观角色的存在; 客户端(Client)角色:调用外观角色访问各个子系统实现不同的业务功能。 其类结构如下图所示: Figure 2. 外观模式类图 我们在软件开发中,经常会有意无意的使用外观模式。比如,MVC模式业务开发中,Service层会屏蔽Dao层的实现细节,对外只暴露一个方法,该方法内部可能会需要使用多个Dao来完成数据库操作。又比如现在流行的微服务架构,API网关就承担着外观角色,客户端直接访问网关,而不会直接去请求各个具体的服务。 Figure 3. API网关示意图 再举一个现在比较专注的例子:智能家居。当你装上了智能家居系统,那么你就可以一键控制家用电器的开关,是不是很舒服?比如,你早上起床,控制器会一键为你打开电动窗帘、播放闹钟、关闭空调等等,再也不用一个一个去操控了。我们看看怎么使用外观模式解决这个问题。 2. 应用案例:智能家居 假设我家安装了一些智能设备:智能空调、智能音响、自动窗帘、智能电灯等,现在我可不想一个个去控制它们。是时候请出超级管家了,它来负责一键操作这些设备。设计类图如下: Figure 4. 智能家居简易设计类图 智能管家作为指挥中心,它具有问好、叫醒起床、上班前告别、下班回家欢迎等功能,当然,假设我们可以通过语音和App操控它。这些功能,智能管家自己不会实现,而是通过调用下边的各个智能设备共同完成。我们看看代码如何实现。 1、智能设备,多个子系统,提供了自身的功能方法。 // 窗帘 class SmartCurtain { public void open() { System.out.println("打开窗帘"); } public void close() { System.out.println("关闭窗帘"); } } // 灯光 class SmartLight { public void open() { System.out.println("打开灯光"); } public void close() { System.out.println("关闭灯光"); } } // 空调 class AirConditioner { public void open() { System.out.println("打开空调"); } public void close() { System.out.println("关闭空调"); } } // 智能音响 class SmartSoundBox { public void play() { System.out.println("播放音乐"); } public void stop() { System.out.println("停止播放音乐"); } } ...