一、门面模式的概念

听懂了这句话就不用往下看了,说明你会了。

听不懂我觉得也正常,如果用一句话能学会就没人看书了。像我这种笨人,都是学会了一个模式,然后往它的定义上套。

二、什么时候使用门面模式

门面模式,也叫外观模式,从我的理解来说算是设计模式中比较简单的几个模式之一。

它的本质就是封装,以及解耦。使用的场景我大致总结如下:

  • 在层次化结构中,可以使用门面模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。这个是最典型的场景,我们的Controller层,都会使用Service层的接口,Service层使用Dao层的接口
  • 调用者(Client)与多个业务接口之间存在很大的依赖性。这是引入门面模式将这些业务接口与调用者解耦,可以提高子系统的独立性和可移植性,比如一个调用者要调用6个接口完成一个业务,那么就可以使用门面模式,把这6个接口封装起来,然后调用者只与门面模式提供的类进行交互

三、怎么使用门面模式

具体如何使用,通过一个例子来说明。

3.1 反例

《一天一模式》— 门面模式-LMLPHP

加入要实现一个解除汽车上的某个设备的功能,一般的设计是上图中所示,伪代码:

public void unBindDevice(String phoneNumber) {
    // 获取用户信息
    User user = userService.findUserByPhoneNumber(phoneNumber);
    // 获取车辆信息
    Vehicle vehicle = vehicleService.findVehicleByUserId(user.getId());
    // 获取设备信息
    DeviceService device = deviceService.findDeviceByVin(vehicle.getVin());
    // 解除绑定
    deviceService.unbind(user.getId(), vehicle.getVin(), device.getId());
}

这么做的缺点是,client对象与3个服务模块有依赖关系,当某一个服务发生变化时,都会影响到client。

这种时候就可以使用门面模式。

3.2 正例

《一天一模式》— 门面模式-LMLPHP

使用门面模式,创建一个Facade类,该类提供一个unbind方法,在这个方法内,实现刚才在client中的的操作:

public class Facade {
    public void unbind(String phoneNumber) {
        // 获取用户信息
        User user = userService.findUserByPhoneNumber(phoneNumber);
        // 获取车辆信息
        Vehicle vehicle = vehicleService.findVehicleByUserId(user.getId());
        // 获取设备信息
        DeviceService device = deviceService.findDeviceByVin(vehicle.getVin());
        // 解除绑定
        deviceService.unbind(user.getId(), vehicle.getVin(), device.getId());
    }
}

client只与Facade类交互,将复杂的业务细节对client进行隐藏,这就是门面模式的应用。

四、总结

门面模式的优点总结:

  • 松散耦合:门面模式接触了客户端与各个业务模块的高耦合,这样在业务发生变化时,客户端不需要进行维护;
  • 简单易用:门面模式使得客户端不再需要了解业务内部的实现,也不需要跟众多模块进行交互,只需要跟门面类交互就可以了;
  • 更好的划分访问层次:通过合理的使用门面模式,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。

直白的说,其实主要就是2点:

  • 发现调用者完成某业务时,需要与好多个业务接口进行交互,就用门面模式进行封装;
  • 在层次结构上,上层调用下层时,下层进行做好封装,不要暴露复杂性,要方便上层使用;

以上就是我对门面模式的一些理解,有不足之处请大家指出,谢谢。

04-23 05:08