likes
comments
collection
share

外观模式白话 - 与中介者、代理模式的区别

作者站长头像
站长
· 阅读数 3

前言

外观模式(Facade Pattern)的定义有点让我摸不着头脑

为子系统中的一组接口提供一个统一的入口,通过引入一个外观角色来简化客户端与子系统间的交互,又叫门面模式。属于结构型模式

子系统?客户端?

还交互上了,用的 HTTPS 吗?

设计模式除了帮助我等程序员设计好代码外,还能解决这样的问题?

emmm可能是翻译原因

看看英文

A facade encapsulates a complex subsystem behind a simple interface. It hides much of the complexity and makes the subsystem easy to use

好嘛

确实有subsystem

但没有client

外观模式

个人认为所谓的子系统可以理解成模块,客户端可以理解成模块的使用者

用大白话讲:外观模式通过一个高层接口来封装模块,并按需暴露模块中的方法,从而降低模块使用的复杂度

以电脑开、关机为例

启动电脑(按电源键):启动CPU、启动内存、启动硬盘

关闭电脑(按电源键):关闭硬盘、关闭内存、关闭CPU

如果没有外观(电源键),那流程很复杂:

外观模式白话 - 与中介者、代理模式的区别

有外观(电源键)就简单了:

外观模式白话 - 与中介者、代理模式的区别

实现

外观模式白话 - 与中介者、代理模式的区别

首先定义一个电脑接口并实现它

// 抽象子系统
public interface IComputer {
    void start();
    void stop();
}

// 子系统1
public class Cpu implements IComputer {
    @Override
    public void start() {
        System.out.println("启动CPU");
    }
    @Override
    public void stop() {
        System.out.println("关闭CPU");
    }
}
// 子系统2
public class Ddr implements IComputer {
    // ...
}
// 子系统3
public class Ssd implements IComputer {
    // ...
}

然后定义一个外观角色PowerSwitchFacade封装功能

public class PowerSwitchFacade {
    private IComputer cpu;
    private IComputer ddr;
    private IComputer ssd;

    public PowerSwitchFacade() {
        this.cpu = new Cpu();
        this.ddr = new Ddr();
        this.ssd = new Ssd();
    }
    public void start() {
        this.cpu.start();
        this.ddr.start();
        this.ssd.start();
    }
    public void stop() {
        this.ssd.stop();
        this.ddr.stop();
        this.cpu.stop();
    }
}

OK,调用一下

// 客户端
public class Client {
    public static void main(String[] args) {
        PowerSwitchFacade powerSwitchFacade = new PowerSwitchFacade();
        powerSwitchFacade.start();
        powerSwitchFacade.stop();
    }
}

把CPU、内存、硬盘的start()都封装在powerSwitchFacade.start()里,客户端开机只需和PowerSwitchFacade交互,即所谓的降低模块使用的复杂度

原来是你

其实 Java 程序员经常使用外观模式(哈哈哈没想到吧)

Java 的三层开发模式DAO->Service->Controller就体现了外观模式的思想

回忆下

基于 Spring 开发时会把 DAO、Service、Controller 注入为Bean作为单例使用

同样的

在外观模式中,通常只需要一个外观类,即它是一个单例

但不等同于整个系统中只有一个外观类哈想想你的 SpringBoot 项目里有多少个 Service 吧骚年~

与中介者模式、代理模式的区别

外观模式在客户端和子系统间增加了一个 Facade 外观角色

看字面意思,这个外观角色挺像个中介者或者代理的

它们仨有啥区别呢?

外观模式:针对客户端和子系统之间,通过一个高层接口简化客户端访问子系统的复杂度

中介者模式:针对子系统内部模块之间,通过一个中介者简化各对象间的相互引用

代理模式:针对单个类,用一个类代表另一个类的功能

总结

外观模式有它的优点:

  1. 它把需要暴露的功能集中在Facade中,隐藏了内部细节,使子系统更加易用
  2. 客户端不再需要了解子系统内部的实现,而且单个子系统改动不会影响到客户端

Java 的三层开发模式DAO->Service->Controller就体现了外观模式的思想

外观模式也有缺点,它不符合开闭原则:新增或删减子系统都会影响到Facade

当然,如果开发需要的话也可以直接使用复杂的subsystem,没有强制说是一定得用外观模式,活学活用最重要~


感谢阅读~不喜勿喷。欢迎讨论、指正