【设计模式】门面模式,其实我们一直都在用。

1,323 阅读4分钟

这是我参与更文挑战的第26天,活动详情查看:更文挑战


👉设计模式目录

什么是门面模式(Facade)

概念

门面模式,又叫做外观模式,属于结构型模式。我个人比较喜欢叫门面模式,因为这个模式是为了隐藏系统内部的复杂性,向外部提供一个统一的接口,使得外部访问该系统更加方便、更加简单

门面模式是迪米特法则的代表,它关心对象和对象之间的组合关系,它主要是想几个对象之间的复杂操作都封装在一个高层次的类中,外部调用无需关心它内部的逻辑,只需要调用自己想要的功能即可。

我们在日常的开发中也会用到门面模式,用过Spring做开发的小伙伴一定知道MVC的层次划分,其中Controller层和Service层都用到了门面模式,它们都封闭了内部的复杂性,为外部提供一个方便调用的接口。我再举一个通俗的例子,想我们去洗衣服,如果是我们自己洗的话,需要先加洗衣液来洗,拧干,洗完过清水,再拧干,再过清水,最后需要拧的更干,这个步骤非常地多;如果使用洗衣机的话,我们就只需要把衣服倒到洗衣机,洗衣服的步骤就由洗衣机来做了。这里的洗衣机就封闭了洗衣服的过程,我们只需要把衣服丢到洗衣机即可。

滑稽脸洗衣机.gif

优点

门面模式满足迪米特法则,它的大部分优点都是跟迪米特法则相似的。

  1. 降低了子系统和调用者间的耦合度,调用者只需要调用这个门面即可,不需要去关心底下有多少个子系统。
  2. 使得调用更加的方便。
  3. 减少了系统的相互依赖,增加了系统的灵活性。只要提供门面不变,无论系统内部的逻辑如何改变都可以。

缺点

不符合开放封闭原则。每次有新的改动都需要去修改门面,想要继承重写,组合都很难完成。

原则

“+”代表遵守,“-”代表不遵守或者不相关

原则开放封闭单一职责迪米特里氏替换依赖倒置接口隔离合成复用
--+---+

适用场景

  1. 模块或子系统中的组件太多了,调用过程十分麻烦。这种情况就需要使用门面模式来提供一个更加方便调用的接口了,不然这个模块使用起来非常复杂。
  2. 模块或子系统内部相对独立。这种情况,我们提供好暗箱操作,减少调用者的使用难度。
  3. 预防低水平人员带来的风险。就是让这个模块使用起来更加简单,让每个人都能使用。

如何实现

想要实现门面模式(外观模式),需要以下两样东西:

  1. 门面(外观)类:负责处理调用子系统的逻辑。
  2. 子系统类:提供系统的部分功能。

上类图

image-20210603152047955

上代码

这里实现洗衣机的例子。

子系统类:SubSystemA/B/C

/**
 * 子系统类
 * 模拟洗衣机的组件:滚筒
 * Created on 2021/6/3.
 *
 * @author xuxiaobai
 */
public class SubSystemA {
    /**
     * 滚动
     */
    public void operate(){
        System.out.println("滚起来。。。。");
    }
}
——————————————————————————
/**
 * 子系统类
 * 模拟洗衣机的组件:排水管
 * Created on 2021/6/3.
 *
 * @author xuxiaobai
 */
public class SubSystemB {
    /**
     * 排水
     */
    public void operate(){
        System.out.println("排水中。。。。");
    }
}
———————————————————————————
/**
 * 子系统类
 * 模拟洗衣机的组件:加水管
 * Created on 2021/6/3.
 *
 * @author xuxiaobai
 */
public class SubSystemC {
    /**
     * 加水
     */
    public void operate(){
        System.out.println("加水。。。。");
    }
}

门面类:Facade

/**
 * 门面类
 * 模拟洗衣机
 * Created on 2021/6/3.
 *
 * @author xuxiaobai
 */
public class Facade {
    private SubSystemA subSystemA=new SubSystemA();
    private SubSystemB subSystemB=new SubSystemB();
    private SubSystemC subSystemC=new SubSystemC();

    /**
     * 洗衣服
     */
    public void operate(){
        System.out.println("开始洗衣服");
        subSystemC.operate();
        subSystemA.operate();
        subSystemB.operate();
        System.out.println("第一遍洗完了");
        subSystemC.operate();
        subSystemA.operate();
        subSystemB.operate();
        System.out.println("第二遍洗完了");
        subSystemC.operate();
        subSystemA.operate();
        subSystemB.operate();
        System.out.println("衣服洗完了,滴滴滴");
    }

}

测试类:FacadeTest

/**
 * Created on 2021/6/3.
 *
 * @author xuxiaobai
 */
public class FacadeTest {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.operate();
        /**
         * 开始洗衣服
         * 加水。。。。
         * 滚起来。。。。
         * 排水中。。。。
         * 第一遍洗完了
         * 加水。。。。
         * 滚起来。。。。
         * 排水中。。。。
         * 第二遍洗完了
         * 加水。。。。
         * 滚起来。。。。
         * 排水中。。。。
         * 衣服洗完了,滴滴滴
         */
    }
}

功成猿满

Facade类内部封装了洗衣机的操作过程,只需要调用operate方法即可完成洗衣操作。

总结

门面模式不符合开放封闭原则,但这也是我们最常使用的设计模式,使用起来不要太方便了,也不会太难,作为Java开发人员,这个设计模式的思想应该是与生俱来的了,唯一需要注意的是每个门面类封装的操作都是在同一个层次的,像一个洗衣机,可以再封装开关电源的方法,但不能封装关总闸的方法。

——————————————————————————————

你知道的越多,不知道的就越多。

如果本文章内容有问题,请直接评论或者私信我。如果觉得我写得还不错的话,点个赞也是对我的支持哦

未经允许,不得转载!