设计模式(12):外观模式

尺有所短,寸有所长;不忘初心,方得始终。

一、外观模式是什么

外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的结构型模式。

【主要作用】:降低访问复杂系统的内部子系统时的复杂度,使得客户端不与系统耦合,外观类与系统耦合。

为子系统中的一组接口提供一个一致的调用,外观模式定义了一个高层接口使子系统更加容易使用。

在日常编码中,我们都在有意无意的大量使用外观模式。

设计模式(12):外观模式

二、外观模式的适用场景

  • 在不同的分层结构中,使用外观模式定义子系统之间的依赖关系。
  • 当一个系统的子系统很多,调用链复杂时,外观模式可以为系统设计一个简单的接口供外界访问。
  • 当客户端与多个子系统之间存在联系时,引入外观模式可将它们分离,客户端与子系统解耦。

三、外观模式结构

  • 抽象外观(Facade)角色:为多个子系统对外提供一个共同的接口。

  • 具体外观(concrete Facade)角色:实现抽象外观角色,持有各个子系统的应用对象,并初始化,重定向客户端请求,操作子系统。

  • 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。

  • 客户(Client)角色:通过一个外观角色访问各个子系统的功能。

设计模式(12):外观模式

四、外观模式实现方式

  • 梳理子系统以及调用关系

  • 在现有子系统的基础上提供一个更简单的抽象外观角色接口,该接口能让客户端独立于众多子系统。

  • 声明具体外观角色类并实现该接口

    具体外观角色将客户端的调用重定向到子系统中。具体外观角色需要对子系统进行初始化。

  • 所有客户端代码仅通过外观来与子系统进行交互

  • 如果外观变得过于臃肿,可以考虑将其部分行为抽取为一个新的专用外观类。

五、外观模式的实现

  • 子系统(Sub System)角色

    /**
    * 子系统(Sub System)角色 子系统1
    */

    public class SubSystem1 {

    public void method(){
    System.out.println("子系统1的方法执行.........");
    }
    }

    /**
    * 子系统(Sub System)角色 子系统2
    */

    public class SubSystem2 {

    public void method(){
    System.out.println("子系统2的方法执行.........");
    }
    }

    /**
    * 子系统(Sub System)角色 子系统3
    */

    public class SubSystem3 {

    public void method(){
    System.out.println("子系统3的方法执行.........");
    }
    }
  • 抽象外观(Facade)角色

    /**
    * 抽象外观(Facade)角色
    */

    public interface Facade {

    public void method1();

    public void method2();
    }
  • 具体外观(concrete Facade)角色

    /**
    * 具体外观(concrete Facade)角色
    */

    public class ConcreteFacade implements Facade{
    /**
    * 持有各个子系统的应用对象,并初始化
    */

    private SubSystem1 subSystem1;
    private SubSystem2 subSystem2;
    private SubSystem3 subSystem3;

    public ConcreteFacade(){
    subSystem1 = new SubSystem1();
    subSystem2 = new SubSystem2();
    subSystem3 = new SubSystem3();
    }

    @Override
    public void method1() {
    subSystem1.method();
    subSystem2.method();
    }

    @Override
    public void method2() {
    subSystem1.method();
    subSystem3.method();
    }
    }
  • 客户端代码实现

    public static void main(String[] args) throws Exception {
    Facade facade = new ConcreteFacade();
    facade.method1();
    facade.method2();
    }
  • 案例输出结果

设计模式(12):外观模式

六、外观模式的优缺点

优点:

  • 完全符合迪米特法则,提高了模块的相对独立性,提高了类的可复用率和系统的扩展性。

  • 降低了子系统与客户端之间的耦合度,子系统的变化不会影响客户端。

  • 对客户屏蔽了子系统组件,减少了客户端处理的对象数目,并使得子系统使用起来更加容易。

  • 降低了系统中的编译依赖性,简化了系统之间的移植过程。

缺点:

  • 不符合开闭原则,增加新的子系统可能需要修改外观类代码。
  • 不能限制客户使用子系统类。

七、外观模式和其他模式的区别

  • 当一个外观对象可以支持需求的情况下可以将【外观】类转换为【单例模式】类。
  • 当只需对客户端代码隐藏子系统创建对象的方式时,【外观模式】可以用【抽象工厂模式】代替实现
  • 【外观模式】和【中介者模式】都是将多个紧密耦合的类中组织起来合作
    • 【外观模式】为子系统中的所有对象定义了一个简单接口, 但是它不提供任何新功能。子系统不会感知到外观的存在,子系统之间可以直接进行交流。
    • 【中介者模式】将系统中组件的沟通行为中心化, 各组件只能感知中介者对象, 无法直接相互交流。

八、总结

在日常编码中,我们会大量使用外观模式,只要是高层模块需要调度多个子模块,我们都可以进行抽象,提供精简的接口,让高层模块可以更加容易地间接调用模块的功能。


原文始发于微信公众号(星河之码):设计模式(12):外观模式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/27146.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!