专栏首页程序猿的大杂烩设计模式之外观模式

设计模式之外观模式

外观模式(Facade)是23种设计模式之一,也称为门面模式。DP中是这么定义外观模式的:

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

一个系统都是由各种大大小小不同功能的类组成的,每一个类都会提供被外部调用的接口,我们可以通过这些接口去使用这些类,但是客户端要一个个的去调用这些类非常的麻烦,而且也会造成客户类与子系统类耦合性高的问题,就如下图:

所以为了解决这种问题,我们需要定义一个高层接口,让这个高层接口去完成各个子系统类接口的调用,客户类就只需要对这个高层接口进行调用即可,这样降低了客户类与子系统类的耦合,也能让客户端更加方便的使用这个系统,这就是外观模式,如下图:

我们再用电脑来举个简单的例子,之所以我们可以很方便的一键式的开启和关闭电脑,就是因为机箱给我们提供了一个开关按钮,这个开关按钮就相当于是一个高层接口,我们只需要知道按这个按钮就能开启电脑,背后的复杂交互我们不需要关心。如果没有这个统一的开关按钮,那么我们想要开启和关闭电脑就得对硬件一个个的去操作了,就如下图:

让我们使用简单的代码来实现这个场景:

package org.zero01.system;

public class CPU {

    public void turnOn() {
        System.out.println("CPU-开");
    }

    public void turnOff() {
        System.out.println("CPU-关");
    }
}

package org.zero01.system;

public class GPU {

    public void turnOn() {
        System.out.println("GPU-开");
    }

    public void turnOff() {
        System.out.println("GPU-关");
    }
}

package org.zero01.system;

public class Memory {

    public void turnOn() {
        System.out.println("内存-开");
    }

    public void turnOff() {
        System.out.println("内存-关");
    }
}

package org.zero01.system;

public class Disk {

    public void turnOn() {
        System.out.println("磁盘-开");
    }

    public void turnOff() {
        System.out.println("磁盘-关");
    }
}

用户代码如下:

package org.zero01.user;

import org.zero01.system.CPU;
import org.zero01.system.Disk;
import org.zero01.system.GPU;
import org.zero01.system.Memory;

public class User {

    public static void main(String[] args) {

        CPU cpu = new CPU();
        GPU gpu = new GPU();
        Memory memory = new Memory();
        Disk disk = new Disk();

        cpu.turnOn();
        gpu.turnOn();
        memory.turnOn();
        disk.turnOn();

        cpu.turnOff();
        gpu.turnOff();
        memory.turnOff();
        disk.turnOff();

    }
}

从用户调用的代码上可以看到,需要逐个去实例化各个硬件的对象,然后还得一个个的去调用开关方法很麻烦。

所以我们要利用外观模式来解决这个问题,先来看看外观模式的结构图:

使用代码实现这个简单的结构,子系统类:

class SubSystemOne{

    public void methodOne() {

        System.out.println("子系统方法一");
    }

}

class SubSystemTwo{

    public void methodTwo() {

        System.out.println("子系统方法二");

    }

}

class SubSystemThree{

    public void methodThree() {

        System.out.println("子系统方法三");

    }

}

class SubSystemFour{

    public void methodFour() {

        System.out.println("子系统方法四");

    }

}

Facade外观类:

package org.zero01.system;

/**
 * 外观类,它需要了解所有子系统类的方法或属性, 并进行处理、组合,以提供给外部调用
 */
public class Facade {

    private SubSystemOne subSystemOne;
    private SubSystemTwo subSystemTwo;
    private SubSystemThree subSystemThree;
    private SubSystemFour subSystemFour;

    public Facade() {
        subSystemOne = new SubSystemOne();
        subSystemTwo = new SubSystemTwo();
        subSystemThree = new SubSystemThree();
        subSystemFour = new SubSystemFour();
    }

    public void MethodA() {
        System.out.println("\n 方法组A() -------- ");
        subSystemOne.methodOne();
        subSystemTwo.methodTwo();
        subSystemFour.methodFour();
    }

    public void MethodB() {
        System.out.println("\n 方法组B() -------- ");
        subSystemOne.methodOne();
        subSystemTwo.methodTwo();
        subSystemThree.methodThree();
    }

}

Client客户端类:

package org.zero01.user;

import org.zero01.system.Facade;

/**
 * 由于Facade的作用,客户端可以根本不知道子系统类的存在,只需要对Facade对象进行操作即可
 */
public class Client {

    public static void main(String[] args) {

        Facade facade = new Facade();

        facade.MethodA();
        facade.MethodB();

    }
}

如上,可以看到,客户端只需要对Facade操作即可,不需要一个个的去对子系统类进行操作。这种模式用得挺多的,因为它完美的体现了依赖倒转原则以及迪米特法则的思想。

使用外观模式重构之前的代码,增加一个外观类:

package org.zero01.system;

public class MainSwitch {

    private CPU cpu;
    private GPU gpu;
    private Memory memory;
    private Disk disk;

    public MainSwitch() {
        cpu = new CPU();
        gpu = new GPU();
        memory = new Memory();
        disk = new Disk();
    }

    public void turnOn() {
        System.out.println("\n开机-------------");
        cpu.turnOn();
        gpu.turnOn();
        memory.turnOn();
        disk.turnOn();
    }

    public void turnOff() {
        System.out.println("\n关机-------------");
        cpu.turnOff();
        gpu.turnOff();
        memory.turnOff();
        disk.turnOff();
    }

}

用户类只需要对这个外观类进行操作即可,就完成了一键式开关机:

package org.zero01.user;

import org.zero01.system.MainSwitch;

public class User {

    public static void main(String[] args) {

        MainSwitch mainSwitch=new MainSwitch();

        mainSwitch.turnOn();
        mainSwitch.turnOff();

    }
}

运行结果:

开机-------------
CPU-开
GPU-开
内存-开
磁盘-开

关机-------------
CPU-关
GPU-关
内存-关
磁盘-关

何时使用外观模式:

至于何时使用外观模式,可以分为三个阶段来说:

1.首先在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观接口Facade,这样可以为每一层复杂的子系统提供一个简单的接口,不仅使得耦合大大降低,也让外部调用更简单。

2.其次,在开发阶段,子系统往往因为不断的重构演化而变化得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也会给外部调用它们的用户带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。

3.第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖它,此时用外观模式也是非常适合的。你可以为新系统开发一个外观Facade类,来为这个设计粗糙或高度复杂的遗留代码提供一个比较清晰简单的接口,让新系统与Facade对象交互,Facade对象则与遗留代码交互所有复杂的工作。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java并发编程(8)- 应用限流及其常见算法

    本文仅针对限流做一些简单的说明,那么何为限流呢?顾名思义,限流就是限制流量,就像你宽带包了1个G的流量,用完了就没了。通过限流,我们可以很好地控制系统的qps,...

    端碗吹水
  • 编写第二个页面:新闻阅读列表页面

    关于Swiper组件的官方描述文档: https://mp.weixin.qq.com/debug/wxadoc/dev/component/swiper.ht...

    端碗吹水
  • 第三个页面:构建新闻详情页面

    在编写从文章列表跳转到新闻详情页的代码之前,先来修改一下之前的页面,之前我们编写了两个模板文件,但是还有两个细节没有完善好,一个是post.wxss中的.pos...

    端碗吹水
  • 设计之禅——外观模式

    平时在我们生活中,我们常常会接触学习各种各样的新事物,而能够快速吸引留住大量客户的都有一个共性,就是简单易学好上手。比如,windows和linux系统,前者比...

    夜勿语
  • 设计模式第一讲-模版方法模式

    模版方法模式是很比较简单的一种模式,也是非常常用的一种设计模式, 相信大家工作过程中直接或间接用到过很多。

    用户2825413
  • 设计模式之结构型模式

    动态代理与静态代理的比较 抽象角色中(接口)声明的所以方法都被转移到调用处理器一个集中的方法中处理 , 我们可以更加灵活和统一的处理众多的方法。

    时间静止不是简史
  • 图解Java设计模式之外观模式

    组建一个家庭影院 : DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,其过程为: 直接用遥控器:统筹各设备开关 开爆米花...

    海仔
  • 【JAVA基础&高级】“面向对象篇” 知识点汇总

    由于近期需要用到基础以及底层的一些知识点,所以借此机会找来了一些学习的资料,用于对 JAVA 面向对象相关的知识点进行复盘、巩固,并且在此将一些重点的知识点做相...

    LCyee
  • 图解Java设计模式之策略模式

    1)有各种鸭子(比如 野鸭、北京鸭、水鸭等)鸭子有各种行为,比如叫、飞行等等。 2)显示鸭子的信息

    海仔
  • 设计模式之模板方法模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决...

    低调小熊猫

扫码关注云+社区

领取腾讯云代金券