11 结构型模式之外观模式(Facade)

1 介绍

1.1 引入

如果客户端要跟许多子系统打交道,那么客户端需要了解各个子系统的接口,比较麻烦。如果有一个统一的“中介”,让客户端只跟中介打交道,中介再去跟各个子系统打交道,对客户端来说就比较简单。

1.1 外观模式的定义与特点

外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

日常编码工作中,我们都在有意无意的大量使用外观模式。只要是高层模块需要调度多个子系统(2个以上的类对象),我们都会自觉地创建一个新的类封装这些子系统,提供精简的接口,让高层模块可以更加容易地间接调用这些子系统的功能。

外观(Facade)模式包含以下主要角色:

  • 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
  • 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。

好处:

  • 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
  • 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。

缺点:

  • 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”

2 案例

简单的实现引入中提到的场景

我们以注册公司为例,假设注册公司需要:

  1. 向工商局申请公司营业执照,拿到备案号
  2. 拿到工商局的备案号,去银行开设账户;

2.1 代码实现

  1. 定义两个模型
package study.wyy.design.facade.model;

import lombok.Data;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/6 16:45
 */
@Data
public class Company {
    /****
     * 公司名称
     */
    private String name;

    /***
     * 公司法人
     */
    private String corporateName;

    /****
     * 公司地址
     */
    private String address;

    /****
     * 备案号
     */
    private String icp;
}

package study.wyy.design.facade.model;

import lombok.Data;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/6 16:56
 */
@Data
public class BankAccount {
    /****
     * 账户号
     */
    private String accountId;

    /***
     * 账户名
     */
    private String accountName;
}

  1. 定义两个服务
    • 公司注册服务
package study.wyy.design.facade.service;

import study.wyy.design.facade.model.Company;

import java.util.UUID;

/**
 * @author wyaoyao
 * @description 工商注册服务
 * @date 2021/1/6 16:50
 */
public class AdminOfIndustryService {

    /***
     * 模拟公司注册,返回公司的备案号
     * @param company
     * @return
     */
   public String registerCompany(Company company){
       System.out.println("工商局公司备案完成");
       return UUID.randomUUID().toString();
   }
}

  • 银行开户服务
package study.wyy.design.facade.service;

import study.wyy.design.facade.model.BankAccount;
import study.wyy.design.facade.model.Company;

import java.util.UUID;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/6 16:55
 */
public class BankService {

    /******
     * 模拟银行开户
     * * @param company
     * @return
     */
    public BankAccount openAccount(Company company){
        BankAccount bankAccount = new BankAccount();
        bankAccount.setAccountId(UUID.fromString(company.getIcp()).toString());
        bankAccount.setAccountName(company.getName());
        System.out.println("银行开户完成");
        return bankAccount;
    }
}

  1. 客户端调用
    public static void main(String[] args) {
        // 1 注册公司
        AdminOfIndustryService adminOfIndustryService = new AdminOfIndustryService();
        Company company = new Company();
        company.setAddress("中国北京");
        company.setCorporateName("张三");
        company.setName("张三网络科技公司");
        String icp = adminOfIndustryService.registerCompany(company);

        // 2 银行开户
        BankService bankService = new BankService();
        company.setIcp(icp);
        BankAccount bankAccount = bankService.openAccount(company);
        
    }

可见客户端使用起来就过于麻烦,这个时候就可以提供一个门面,将这两个过程封装起来:

package study.wyy.design.facade.facade;

import study.wyy.design.facade.model.BankAccount;
import study.wyy.design.facade.model.Company;
import study.wyy.design.facade.service.AdminOfIndustryService;
import study.wyy.design.facade.service.BankService;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/6 17:14
 */
public class CompanyFacade {

    private final AdminOfIndustryService adminOfIndustryService;

    private final BankService bankService;

    public CompanyFacade() {
        this.adminOfIndustryService = new AdminOfIndustryService();
        this.bankService = new BankService();
    }

    public void register(Company company){
        // 1 注册公司
        String icp = adminOfIndustryService.registerCompany(company);
        // 2 银行开户
        company.setIcp(icp);
        BankAccount bankAccount = bankService.openAccount(company);
    }
}

此时客户端使用就变得简单了:

    public static void main(String[] args) {
        CompanyFacade companyFacade = new CompanyFacade();
        Company company = new Company();
        company.setAddress("中国北京");
        company.setCorporateName("张三");
        company.setName("张三网络科技公司");
        companyFacade.register(company);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值