黑盒——外观模式

外观模式

​ Facade Pattern:外观模式,是GoF23种设计模式之中属于结构型模式的一种。外观模式的定义就是为一组接口外面在包装一个一致的接口,通过这个一致的接口再去访问被包装的一组接口。

​ 说起来可能是有点绕,但是可以把这个外观模式想象成黑盒,类比于熟悉的黑盒测试,当我们需要对一个模块进行功能测试的时候,使用黑盒测试,此时我们是不知道这个模块的具体实现的代码的,很有可能的是我们都得不到这个模块的代码,只有这个模块抛出来可以给我们统一调用的API接口而已。

​ 这可以类比于外观模式的目的和定义,外观模式就是在将一组接口包装起来成一个接口,外界用户甚至都不知道这些接口,只能直接通过那一个统一的接口调用和返回自己所需要的信息。

结构

外观模式类图
通过类图简单的分析一下:

  • 外观类:这个是外观模式的中心,这个外观类里面包含着所有接口,知道哪些接口可以处理哪些请求,完成对应的服务,而且用户也是直接调用的这个类,用户是不知道被外观类包含的接口存在的。
  • 功能接口(这只是一个描述而已,也可以是子系统类等等):这些是需要被包含的类的集合,当然可以是接口也可以是类,但是这些功能接口都是需要包含到外观类之中。
举例说明
  • 外观模式的使用很多很多,一说起来就可以知道的就是前后端分离了。对于前后端完全分离的开发,前端是完全不知道后端在干什么的,后端也不会管前端在干什么,前端只需要调用后端给出的API接口,后端也只需要编写API接口,两者谁也不认识谁,谁也不需要了解谁,拿来就可以用。

  • 再打个比方,比如我们自己买的笔记本电脑,我们收到笔记本电脑之后需要怎么使用?很简单,按下开机键,开机,就可以使用了。

    至于里面的什么主板,什么CPU,什么显卡,什么散热器,什么SSD这些都不需要我们自己组装,也不需要我们制作,可以做的就是拿起来就用。

    这个位置就可以形象的吧笔记本电脑当成一个外观类,而里面的所有其他东西都是被包装的功能接口的体现,不论是CPU,显卡的硬件还是Windows,Mac,Lunix系统的软件,这些是我们不知道或者不需要管理的。

  • 说个高级点的例子,对于Spring Cloud全家桶的使用,搭建分布式微服务的应用就是这样的,每个微服务之间都是独立开发的,你不了解我,我不了解你,但是我可以使用你,对外都是一致的抛出API接口,对内则是每个微服务自己解决对方的请求并且给出答复,当然这个例子不是很恰当啊,仅当是听听就可以了。

注意
  • 外观类,之前说过是需要包含所有子系统接口的,这就不符合开闭原则了,因为如果后期需要加东西,这是需要修改源代码的,这就破坏了开闭原则的定义规范了。
  • 但是外观模式最为重要的一个点就是松耦合的特征,解决掉客户端和系统的耦合关系,客户端不需要按照自己的要求在系统中找到对应的实现接口,而是直接通过外观类,至于其他的事情就不该客户端来办了,只需要等待最后的结果就行了。
  • 还有个好处就是提高了安全性,重要的,主要的接口都不需要对外暴露,直接封装起来,变成一个黑盒子,外部的用户调用只知道暴露出来的东西,其他的都不知道,算是加了一层防护保护。
一个小DEMO
  1. 场景

    来个简单的Demo,这里我们有三个子系统,和一个包含三个子系统的外观类,可以叫他是接待员,负责收集用户请求和分发处理方式的作用的。

  2. 定义好我们的子系统

    package com.facade;
    /**
     * 外观模式——需要被隐藏起来交给外观类托管的子系统A
     * @author WQ
     */
    public class SubsystemA {
    	public void show() {
    		System.out.println("我是子系统A的处理方法!");
    	}
    }
    //------------------------------------------------------------
    package com.facade;
    /**
     * 外观模式——需要被隐藏起来交给外观类托管的子系统B
     * @author WQ
     */
    public class SubsystemB {
    	public void show() {
    		System.out.println("我是子系统B的处理方法!");
    	}
    }
    //-------------------------------------------------------
    package com.facade;
    /**
     * 外观模式——需要被隐藏起来交给外观类托管的子系统C
     * @author WQ
     */
    public class SubsystemC {
    	public void show() {
    		System.out.println("我是子系统C的处理方法!");
    	}
    }
    
  3. 外观类,托管所有的子系统对象,并且提供外部访问的入口

    package com.facade;
    /**
     * 外观模式——外观类
     * 	托管所有的子系统对象,并且提供给外界调用的入口
     * @author WQ
     */
    public class Facade {
    	// 托管的对象
    	SubsystemA a;
    	SubsystemB b;
    	SubsystemC c;
    	// 构造各个对象
    	public Facade() {
    		a = new SubsystemA();
    		b = new SubsystemB();
    		c = new SubsystemC();
    	}
    	//对外提供的方法调用入口
    	public void methodA() {
    		a.show();
    	}
    	public void methodB() {
    		b.show();
    	}
    	public void methodC() {
    		c.show();
    	}
    	public void methodABC() {
    		a.show();
    		b.show();
    		c.show();
    	}
    }
    
  4. 客户端调用,也就是测试类了

    package com.facade;
    /**
     * 外观模式——测试类
     * @author WQ
     */
    public class Main {
    	public static void main(String[] args) {
    		// 首先外观类用户是需要知道的
    		Facade facade = new Facade();
    		// 用户说:我要使用子系统A的功能
    		facade.methodA();
    		// 用户说:我要使用子系统B的功能
    		facade.methodB();
    		// 用户说:我要使用所有子系统的功能
    		facade.methodABC();
    	}
    }
    
  5. 测试走一波

    我是子系统A的处理方法!
    我是子系统B的处理方法!
    我是子系统A的处理方法!
    我是子系统B的处理方法!
    我是子系统C的处理方法!
    

完成!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值