把书读薄 | 《设计模式之美》设计模式与范式(结构型-门面模式)

0x0、引言

?页面写完,等后端接口联调,继续啃《设计模式之美》,本文对应设计模式与范式:结构型(52),门面模式 (Facada Pattern),又称 外观模式

了解定义,适用场景、优缺点和使用示例就差不多了~

Tips:二手知识加工难免有所纰漏,感兴趣有时间的可自行查阅原文,谢谢。


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 (子系统) → 子系统不知道门面的存在,对于它而言,门面仅仅是另外一个客户端而已;

门面模式通过引入一个外观角色来简化客户端与子系统间的交互,为复杂子系统的调用提供一个统一的入口,使得子系统与客户端的耦合度降低,客户端调用方便。

门面模式并不会给系统增加任何新功能,仅仅是 简化调用,统一操作,当然也有缺点:降低了可靠性,过多子系统同依赖一个门面系统,门面系统挂了可能导致子系统无法使用;子系统扩展升级没通知门面系统,可能会造成系统的不可用。

使用场景

  • 解决易用性问题;

  • 解决性能问题; (客户端访问服务需调用多个接口,外观模式简化一波)

  • 解决分布式事务问题;

  • 作为一个简洁的中间层,联合更多系统来扩展原有系统;

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享