设计模式(十一):门面模式

Published on 2024-03-12 14:27 in 分类: 博客 with 狂盗一枝梅
分类: 博客

一、门面模式定义

门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如下:Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。)

门面模式注重“统一的对象”,也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生。通用类图如下所示

门面模式.drawio

门面模式的类图非常简单,但是子系统可以非常复杂,简单的说,门面对象是外界访问子系统内部的唯一通道,不管子系统内部是多么杂乱无章,只要有门面对象在,就可以做到“金玉其外,败絮其中”。

二、一个案例

现在智能家居概念比较流行,什么是智能家居呢?比方说,晚上下班回家了,打开门的时候客厅灯光自动就亮了,窗帘自动打开,音响自动播放起你喜欢的音乐。。。我们使用代码模拟下这个功能,类图如下

门面模式-智能家居类图案例.drawio

1、智能家居案例源码示例

灯光类

public class Lamp {

    public void open() {
        System.out.println("灯光打开");
    }


    public void close() {
        System.out.println("灯光关闭");
    }
}

窗帘类

public class Curtain {

    public void open() {
        System.out.println("窗帘打开");
    }


    public void close() {
        System.out.println("窗帘关闭");
    }
}

CD播放器类

public class CDPlayer {

    public void open() {
        System.out.println("CD播放器开机中");
    }

    public void play(String music) {
        System.out.println("播放音乐:" + music);
    }

    public void stop(String music) {
        System.out.println("停止播放音乐:" + music);
    }

    public void shutdown() {
        System.out.println("CD播放起关机中");
    }
}

音乐播放器类

public class MusicPlayer {
    
    CDPlayer cdPlayer = new CDPlayer();
    
    public void playFavoriteMusic() {
        cdPlayer.open();
        String music = chooseOneFavoriteMusic();
        cdPlayer.play(music);
    }

    private String chooseOneFavoriteMusic() {
        return "周杰伦的双节棍";
    }
}

中控类

public class CentralControl {

    private Lamp lamp = new Lamp();
    private Curtain curtain = new Curtain();
    private MusicPlayer musicPlayer = new MusicPlayer();

    public void getOffWorkAction() {
        //打开灯光
        lamp.open();
        //打开窗帘
        curtain.open();
        //播放一首音乐
        musicPlayer.playFavoriteMusic();
    }

}

启动类

public class Main {

    public static void main(String[] args) {
        CentralControl centralControl = new CentralControl();
        centralControl.getOffWorkAction();
    }
}

运行结果

灯光打开
窗帘打开
CD播放器开机中
播放音乐:周杰伦的双节棍

2、案例分析

试想一下,如果没有中控系统,我们回到家想要做这些事情,需要怎么做,需要手动打开灯光,走到窗边打开窗帘,然后打开CD播放器,找到一首想听的歌播放。。。是不是似乎有点麻烦?有了智能中控系统,我们只需要告诉中控系统,我下班回家了,中控系统就会帮我们调用各个子系统的方法完成上面一系列的事情,我到家之后就坐在沙发上享受岁月静好就行了(哈哈)

在这个案例中,中控系统就是“门面”,它负责和各个子系统(音乐播放器、窗帘、灯光)交互,并对人屏蔽了其中的细节。

三、总结

1、门面模式的优点

● 减少系统的相互依赖

想想看,如果我们不使用门面模式,外界访问直接深入到子系统内部,相互之间是一种强耦合关系,你死我就死,你活我才能活,这样的强依赖是系统设计所不能接受的,门面模式的出现就很好地解决了该问题,所有的依赖都是对门面对象的依赖,与子系统无关。

● 提高了灵活性

依赖减少了,灵活性自然提高了。不管子系统内部如何变化,只要不影响到门面对象,任你自由活动。

● 提高安全性

想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到。

2、门面模式的缺点

面模式最大的缺点就是不符合开闭原则,对修改关闭,对扩展开放,看看我们那个门面对象吧,它可是重中之重,一旦在系统投产后发现有一个小错误,你怎么解决?完全遵从开闭原则,根本没办法解决。继承?覆写?都顶不上用,唯一能做的一件事就是修改门面角色的代码。

3、门面模式的使用场景

● 为一个复杂的模块或子系统提供一个供外界访问的接口

● 子系统相对独立——外界对子系统的访问只要黑箱操作即可

● 预防低水平人员带来的风险扩散

比如一个低水平的技术人员参与项目开发,为降低个人代码质量对整体项目的影响风险,一般的做法是“画地为牢”,只能在指定的子系统中开发,然后再提供门面接口进行访问操作。


#设计模式
目录