15-Java代码审计-设计模式-门面模式

120 阅读4分钟

Java设计模式-门面模式(Facade Pattern)

目录

  • 什么是门面模式
  • 门面的实现方式
  • JavaSE门面模式的应用
  • Struts2门面模式的应用

门面模式提供了内部子系统的访问接口,只简单的转发,不做业务处理

一、什么是门面模式

门面模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

门面模式有点像防火墙NAT端口转发,想访问我的内部系统,得先通过防火墙开端口,外网端口映射到内网端口,只是转发而已不做任何处理。

门面模式还有个作用是减少对象之间的耦合关系,如果外部系统在请求内部系统时可以访问内部系统的任意子系统,那么耦合关系将变得非常复杂,封装一个门面类,门面类负责将请求转发到子系统,是不是有点像命令模式?无论你点什么菜,都要经过服务员(请求者(Invoker)角色),服务员负责通知厨师。他们的区别我们后面再总结

二、门面模式的实现方式

举个去医院看病的例子,一般都需要先看医生、化验、复诊、结算,很多老人没有办法自己做完所有的流程,但子女都忙,所以医院有了陪诊员的角色,它会帮我们接触所有医院各个部门的人

image-20230318162234845

下半部分是使用门面模式之后的UML图,实现代码如下

package org.Facade.version1;

class Register{
    public void register(){
        System.out.println("挂号......");
    }
}
class Doctor{
    public void talk(){
        System.out.println("医生看病......");
    }
}
class Nurse{
    public void drawBlood(){
        System.out.println("护士抽血......");
    }
}
class Cashier{
    public void pay(){
        System.out.println("缴费......");
    }
}
class Servicer{
    private Register register = new Register();
    private Doctor doctor = new Doctor();
    private Nurse nurse = new Nurse();
    private Cashier cashier = new Cashier();
    public Servicer(){
        System.out.println("陪诊员负责完成所有看病业务");
    }
    private void register(){
        register.register();
    }
    private void talk(){
        doctor.talk();
    }
    private void drawBlood(){
        nurse.drawBlood();
    }
    private void pay(){
        cashier.pay();
    }
    public void service(){
        this.register();
        this.talk();
        this.drawBlood();
        this.pay();
    }

}
public class TestFacade {
    public static void main(String[] args) {
        Servicer servicer = new Servicer();
        servicer.service();
    }
}
// 运行结果
陪诊员负责完成所有看病业务
挂号......
医生看病......
护士抽血......
缴费......

门面模式除了暴露的service是public其它的都是private,保证了只暴露一个统一接口,是不是非常简单

门面模式和命令模式的不同

  1. 门面模式是结构型模型,命令模式是行为型模型
  2. 门面模式关注的是如何封装实现结构,命令模式关注方法间的通信解耦
  3. 门面关注的是整体操作,命令模式关注的是内部细节操作,例如命令模式可以撤回
  4. 门面模式不符合开闭原则(需要修改门面),命令模式符合(只需要增加命令类)

门面模式和命令模式的相同之处

  1. 都是实现客户端与最终执行者的解耦
  2. 逐渐增加系统复杂性,门面模式的门面类会不断庞大复杂;命令模式的命令类会逐渐增加;

门面模式的缺点

  1. 不符合开闭原则,新增接口需要修改门面类

三、JavaSE门面模式的应用

3.1 java.lang.Class是门面模式

该类对外提供了JDK底层操作JVM的方法,Class类就是门面类

image-20230318171312909

image-20230318171336847

3.2 slf4j典型的门面模式

随着日志的的发展,目前用的较多有JDK自带的jul,log4j(已逐步淘汰)、log4j2、logback等。较大的系统,会拆分为各个微服务,最后再进行互相调用,如果各个微服务项目经理之间未达成共识,可能每个服务用的日志还不一样,比如有的小组用的jul,有的小组用的log4j,这样给后期维护运维就带来了一些难题

因此我们在使用日志的时候需要去加一层日志门面也就是slf4j,slf4j和具体日志对接的时候,需要配置桥接器,就可以使用了,各个日志插件的桥接器如下:

image-20230318171502223

如果项目合并使用的时候,因为多日志就会有些影响了,这样就不得不修改其中一端,造成了一些不必要的工作量,在阿里开发规范中,就有这样一条: 强制:应用中不可直接使用日志系统(log4j、logback)中的 API ,而应依赖使用日志框架 SLF4J 中的 API 。使用门面模式的日志框架,有利于维护和各个类的日志处理方式的统一。

四、Struts2门面模式的应用

暂未发现,如果读者有发现,请联系我添加,谢谢