设计模式——外观模式(Facade)

外观模式又称门面模式,这是我们在开发过程中经常会用到的一种设计模式,很多时候甚至我们在使用这种设计模式的时候自己都没有意识到,因为这种设计模式的思想非常的简单,笔者也是最近在学习设计模式的时候才知道这种方式叫做外观模式。

一、外观模式概念

外观模式(Facade)属于结构型设计模式,它通过向客户端提供一个可以访问系统的接口,向客户端屏蔽系统底层的复杂实现,使客户端可以只用关注这个接口的功能,从而实现客户端与系统底层实现的解耦。

设计模式——外观模式(Facade)_第1张图片

在上图中,Facade就是系统对外开放的接口组,客户端通过调用Facade中提供的接口来间接的调用系统中的各个模块。最近服务架构上比较流行微服务这种设计,这种架构设计就是将一个大的系统拆分成一个个的子系统,然后通过dubbo接口或者Spring Cloud等将服务接口暴露出去来供其他业务方调用,像这种微服务暴露出来的接口就是类似于使微服务的门面,其他的业务方只需要关心这个接口的功能是什么,至于这些功能是怎么调用微服务中的各个功能的,就只要交给Facade去处理就好了。

二、使用场景

1.在设计系统初期,应该有意识地将系统进行层级拆分,定义每一层的层级接口入口,底层应该尽可能向上屏蔽细节,这样的代码会具有更好的可维护性,也更加的易于理解。

2.随着开发的业务越来越复杂,应该尽可能地将那些复杂的业务代码封装成一个简单易懂的接口,增加一个外观模式来供业务方进行调用,避免业务方陷入细节的洪流中。

三、示例

这里以发送短信的业务为例,发送短信这个业务主要分为短信请求发送方(客户端),短信发送系统,在短信发送系统中并不是直接将短信发送出去就完事的,它会涉及多个业务功能,包括短信文本内容校验、手机号检验、短信记录存数据库、发送短信等。我们首先给出各个子功能的模块:

文本校验:

public class ContentVerify{

    public boolean isValidContent(String content){
        //内容判空
        //敏感词检测
        return  是否有效文本
    }
}

手机号校验:

public class PhoneVerify{
    public boolean isValidPhoneNum(String phoneNum){
        //对手机号进行校验
    }
}

短信记录存数据库:

public class SmsReocrdService{
    
    @Autowired
    private SmsRecordDao smsRecordDao;

    public boolean insertSmsRecord(SmsRecord sms){
        //进行一些其他的处理
        return smsRecordDao.insert(sms);
    }
}

发送短信:

public class SmsSender{
    
    @Autowired
    private HttpClinet httpClient;

    public boolean send(SmsDto sms){
        //将短信内容封装成http请求参数
        return httpClient.post(url,param,header);
    }
}

对于要发送短信的业务方来说,他们才不关心什么时候存数据库、要不要存数据库,也不关心怎么来进行短信的发送,他们的诉求很简单,就是我把要发送的内容和手机号给你,剩下的事情你帮我全做了。OK,那我们就用外观模式对上述的各个功能进行组合封装,然后向业务方暴露最简单的调用接口就行了。

SmsSendFacade:

public class SmsSendFacade{

    @Autowwired
    private SmsSender smsSender;

    @Autowired
    private SmsRecordService smsRecordService;

    @Autowired
    private ContentVerify contentVerify;

    @Autowired
    private PhoneVerify phoneVerify;

    public boolean sendSms(String content,String phoneNum){
        if(!contentVerify.isValidContent){
            return false;
        }
        if(!phoneVerify.isValidPhone){
            return false;
        }
        //转换成数据库存储的对象
        SmsRecord smsRecord = convert(content,phoneNum);
        smsRecordService.insertSmsRecord(smsRecord);
        SmsDto smsDto = convertDto(content,phoneNum);
        return smsSender.send(smsDto);
    }
    
}

最后我们来看一下业务方:

public class Client{
    
    @Autowired
    private SmsSendFacade smsSendFacade;

    public void sendSms(){
        //生成需要发送的文本内容content
        //获取需要发送对象的手机号phoneNum
        if(smsSendFacade.send(content,phoneNum)){
            System.out.println("短信发送成功");
        }
    }
}

四、小结

从上面的示例可以看出来,外观模式的概念和应用很简单,主要职责就是将底层实现细节进行封装、对外或对上暴露调用接口,实现客户端与系统以及底层与上层交互的解耦。但是这种设计模式也有一些缺点,比如不符合设计模式的开闭原则,要对它进行修改的话很麻烦,这就需要我们在实际的工作中有所取舍了。

你可能感兴趣的:(设计模式)