设计模式 - 门面模式:如何简化复杂的系统

在这里插入图片描述


概述

门面模式(Facade pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的、更高层次的接口,使子系统更易于使用。门面模式的本质是简化外部系统使用内部多个子系统的使用方式。它将多个复杂的接口功能进行统一封装,为使用者提供一个简化的视图,让系统调用变得更加方便。

与代理模式不同的是,代理模式通常只代理某一个接口,而门面模式则可以代理多个接口。

模式核心原理

门面模式主要包含两个关键角色:

  • 门面系统(Facade):负责处理来自调用者的请求,并将请求分派给适当的子系统进行处理。
  • 子系统(Subsystems):代表某个领域内的功能实现,例如订单、用户、支付等,专门处理由门面系统指派的任务。

一个常见的例子是电脑的开机按钮。用户按下按钮,电脑就会启动,但用户不需要关心电脑如何运行CPU、启动内存、读取硬盘等复杂的内部过程。开机按钮就是一个门面,它简化了用户与复杂系统之间的交互。

门面模式封装了子系统的复杂性,只要门面系统与子系统的交互不发生改变,子系统的独立演化和内部变化就不会影响到门面系统。

常见应用场景

门面模式常用于以下场景:

  • 简化复杂系统:例如,一个包含订单、商品、支付、会员等子系统的电商平台,用户通过一个门户网站或手机App(门面系统)就能轻松完成购物。
  • 减少客户端处理的系统数量:在Web应用中,DAO(数据访问对象)层就是一个门面,它简化了数据库操作,让客户端无需直接处理数据库连接等复杂过程。
  • 为一个系统(或对象)服务于多个系统(或对象):例如,线程池ThreadPool就是一个门面模式,它为系统提供统一的线程创建、销毁和使用接口。
  • 扩展原有系统:当需要新增功能(如人脸识别)时,可以通过门面系统方便地集成第三方服务,而无需自行开发。
  • 作为简洁的中间层:门面模式可以用来隐藏或封装系统中的分层结构。例如,在秒杀系统中,将商品库存数据统一放在Redis中间层,可以为不同的服务(如秒杀详情页、购物车)提供统一的调用入口。

UML

调用门面接口
统一接口
Client
+operation()
Facade
+operation1()
+operation2()
SubsystemA
+methodA()
SubsystemB
+methodB()
SubsystemC
+methodC()

图例说明:

  • Client (客户端): 客户端是门面模式的使用者。它不直接与复杂的子系统进行交互,而是通过调用 Facade 提供的高级接口来完成操作。
  • Facade (门面): 这是门面模式的核心。它包含并协调一个或多个子系统。门面提供一个或多个简化的方法(如 operation1()operation2()),这些方法在内部会调用和组合子系统中的相应方法。
  • SubsystemA, SubsystemB, SubsystemC (子系统): 这些是实现具体功能的类。每个子系统都专注于特定的任务,例如处理数据、执行某个操作等。它们对门面是不可见的,客户端通常不需要直接访问它们。

案例

我们将通过一个简单的智能家居系统来演示门面模式的实现。该系统包含三个子系统:Light(灯光)、Thermostat(恒温器)和StereoSystem(音响系统)。我们将创建一个HomeTheaterFacade作为统一的门面,用户通过它来简化“观影”和“派对”等复杂场景的操作。

1. 定义子系统

首先,我们创建三个子系统类。

Light.java

public class Light {
    public void on() {
        System.out.println("灯光已打开");
    }

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

    public void dim(int level) {
        System.out.println("灯光调暗至 " + level + "%");
    }
}

Thermostat.java

public class Thermostat {
    public void setTemperature(int temp) {
        System.out.println("恒温器温度设置为 " + temp + " 摄氏度");
    }

    public void fanOn() {
        System.out.println("恒温器风扇已打开");
    }
}

StereoSystem.java

public class StereoSystem {
    public void on() {
        System.out.println("音响系统已打开");
    }

    public void off() {
        System.out.println("音响系统已关闭");
    }

    public void setVolume(int volume) {
        System.out.println("音响音量设置为 " + volume);
    }

    public void setMode(String mode) {
        System.out.println("音响模式设置为 " + mode);
    }
}

2. 创建门面

接下来,我们创建HomeTheaterFacade类,它将调用上述子系统来完成“观影模式”和“派对模式”。

HomeTheaterFacade.java

public class HomeTheaterFacade {
    private Light light;
    private Thermostat thermostat;
    private StereoSystem stereoSystem;

    public HomeTheaterFacade() {
        this.light = new Light();
        this.thermostat = new Thermostat();
        this.stereoSystem = new StereoSystem();
    }

    // 统一的“观影模式”操作
    public void watchMovie() {
        System.out.println("\n正在进入观影模式...");
        light.dim(10);
        thermostat.setTemperature(22);
        stereoSystem.on();
        stereoSystem.setMode("Movie");
        stereoSystem.setVolume(20);
        System.out.println("观影模式已启动!");
    }

    // 统一的“派对模式”操作
    public void startParty() {
        System.out.println("\n正在启动派对模式...");
        light.on();
        thermostat.setTemperature(25);
        thermostat.fanOn();
        stereoSystem.on();
        stereoSystem.setMode("Music");
        stereoSystem.setVolume(35);
        System.out.println("派对模式已启动!");
    }

    // 统一的“关闭所有”操作
    public void endAll() {
        System.out.println("\n正在关闭所有系统...");
        light.off();
        stereoSystem.off();
        System.out.println("所有系统已关闭!");
    }
}

3. 客户端调用

最后,我们创建Client类,来演示如何通过门面系统进行操作。

Client.java

public class Client {
    public static void main(String[] args) {
        HomeTheaterFacade facade = new HomeTheaterFacade();

        // 客户端只与门面系统交互,无需关心内部复杂性
        facade.watchMovie();

        System.out.println("\n---");

        facade.startParty();

        System.out.println("\n---");

        facade.endAll();
    }
}

运行结果

运行Client类,你将看到以下输出:

正在进入观影模式...
灯光调暗至 10%
恒温器温度设置为 22 摄氏度
音响系统已打开
音响模式设置为 Movie
音响音量设置为 20
观影模式已启动!

---

正在启动派对模式...
灯光已打开
恒温器温度设置为 25 摄氏度
恒温器风扇已打开
音响系统已打开
音响模式设置为 Music
音响音量设置为 35
派对模式已启动!

---

正在关闭所有系统...
灯光已关闭
音响系统已关闭
所有系统已关闭!

这个案例清楚地展示了门面模式如何通过watchMovie()startParty()endAll()等方法,简化了客户端的操作,将多个子系统的复杂交互封装在门面内部。客户端只需调用一个方法,就能触发一系列预设的复杂操作,从而大大提升了系统的易用性。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值