0x1、定义
为子系统提供一组统一的接口,定义一个更高层接口让子系统更易用。
从定义可以看出门面模式的本质就是 统一多个接口的功能
,简化外部系统使用内部多个子系统的使用方式。
举个形象的例子:电表箱
网络异常,图片无法展示
|
主卧、餐厅、阳台等可以看做是 子系统,而电表箱就是 更高层的接口,通过电表箱可以对每个子系统进行电源控制。
而扩展到实际开发中的例子:
A系统提供a、b、c、d四个接口,B系统完成某个功能,要调用A系统的a、b、d接口,利用门面模式,我们可以提供一个包裹了a、b、d接口调用的门面接口x供系统B直接使用。
这样做的好处:B不用调三次接口,提高了响应速度,更易用;
- 如果门面接口不多,完全可以跟非门面接口放在一块,也不需要特殊标记,当作普通接口来用就好;
- 如果门面接口很多,可以在已有接口之上,重新抽象出一层,专门放置门面接口,从类、包命名上与原接口层做区分;
- 如果门面接口特别多,且很多都是跨多个子系统的,可以将门面接口放到一个新的子系统中;
和代理模式最根本的不同:门面模式可能代理多个接口,而代理模式通常只是代理某个接口;
0x2、写个简单例子
以上面的电表箱为例子写下代码吧:
// 子系统角色 public class Bedroom { public void powerOff() { System.out.println("断开卧室供电"); } public void powerOn() { System.out.println("打开卧室供电"); } } public class Restaurant { public void powerOff() { System.out.println("断开厨房供电"); } public void powerOn() { System.out.println("打开厨房供电"); } } public class Balcony { public void powerOff() { System.out.println("断开阳台供电"); } public void powerOn() { System.out.println("打开阳台供电"); } } // 门面角色 public class ElectricBox { private Bedroom bedroom; private Restaurant restaurant; private Balcony balcony; public ElectricBox(Bedroom bedroom, Restaurant restaurant, Balcony balcony) { this.bedroom = bedroom; this.restaurant = restaurant; this.balcony = balcony; } public void powerOnAll() { System.out.println("=== 打开所有供电=== "); bedroom.powerOn(); restaurant.powerOn(); balcony.powerOn(); } public void powerOffAll() { System.out.println("=== 断开所有供电 === "); bedroom.powerOff(); restaurant.powerOff(); balcony.powerOff(); } public void bedroomPowerOn() { System.out.println("=== 打开卧室供电 === "); bedroom.powerOn(); } } // 测试用例 public class FacadeTest { public static void main(String[] args) { ElectricBox box = new ElectricBox(new Bedroom(), new Restaurant(), new Balcony()); box.powerOnAll(); box.powerOffAll(); box.bedroomPowerOn(); } }
运行结果输出如下:
网络异常,图片无法展示
|
顺手画下UML类图和介绍下两个角色:
网络异常,图片无法展示
|
- Facade (门面角色) → 负责处理子系统调用逻辑,一般没有实际的具体业务,只是一个委托类;
- SubSystem (子系统) → 子系统不知道门面的存在,对于它而言,门面仅仅是另外一个客户端而已;
门面模式通过引入一个外观角色来简化客户端与子系统间的交互,为复杂子系统的调用提供一个统一的入口,使得子系统与客户端的耦合度降低,客户端调用方便。
门面模式并不会给系统增加任何新功能,仅仅是 简化调用,统一操作
,当然也有缺点:降低了可靠性,过多子系统同依赖一个门面系统,门面系统挂了可能导致子系统无法使用;子系统扩展升级没通知门面系统,可能会造成系统的不可用。
使用场景
- 解决易用性问题;
- 解决性能问题; (客户端访问服务需调用多个接口,外观模式简化一波)
- 解决分布式事务问题;
- 作为一个简洁的中间层,联合更多系统来扩展原有系统;