设计模式之外观模式

设计模式中的外观模式(Facade Pattern)是一种简化系统接口的模式,它通过提供一个统一的高层接口来访问子系统中的一群接口。这种模式可以提高系统的可维护性和可扩展性,同时降低了客户端与多个子系统之间的耦合度。下面是一个详细的介绍和Java代码示例,该示例描述了一个家庭影院系统,包括电视、DVD播放机、立体声音响等多个组件,以及一个外观类来简化这些组件的操作。

一、外观模式的作用

外观模式主要用于以下几种情况:

1、简化接口

当一个系统变得非常复杂,并且客户端需要一个简单的接口来与之交互。

2、降低依赖

通过引入外观类,可以减少系统之间的依赖性。

3、封装变化

如果子系统中的接口发生变化,可以通过调整外观类来应对,而不需要改变客户端代码。

4、遵循迪米特法则

一个软件实体应当尽可能少地与其他实体发生相互作用。

二、外观模式的角色

1、子系统类(Subsystem Classes):

它们可以接受请求。

2、外观类(Facade Class):

提供一个简单的接口给客户端。

三、java代码示例

1、子系统类定义

首先定义各个子系统类:

java 复制代码
public class DVDPlayer {
    private String description;

    public DVDPlayer(String description) {
        this.description = description;
    }

    public void on() {
        System.out.println(description + " 开启");
    }

    public void off() {
        System.out.println(description + " 关闭");
    }

    public void eject() {
        System.out.println(description + " 弹出光盘");
    }

    public void playMovie(String movie) {
        System.out.println(description + " 播放电影 " + movie);
    }
}

public class TV {
    private String description;

    public TV(String description) {
        this.description = description;
    }

    public void on() {
        System.out.println(description + " 开启");
    }

    public void off() {
        System.out.println(description + " 关闭");
    }

    public void setChannel(int channel) {
        System.out.println(description + " 设置频道到 " + channel);
    }
}

public class Amplifier {
    private String description;

    public Amplifier(String description) {
        this.description = description;
    }

    public void on() {
        System.out.println(description + " 开启");
    }

    public void off() {
        System.out.println(description + " 关闭");
    }

    public void setVolume(int level) {
        System.out.println(description + " 设置音量到 " + level);
    }
}

public class PopcornPopper {
    private String description;

    public PopcornPopper(String description) {
        this.description = description;
    }

    public void on() {
        System.out.println(description + " 开启");
    }

    public void off() {
        System.out.println(description + " 关闭");
    }

    public void pop() {
        System.out.println(description + " 开始爆米花制作");
    }
}

2、外观类定义

接下来定义一个遥控器的外观类,用来简化用户对家庭影院系统的操作:

java 复制代码
public class HomeTheaterFacade {
    private DVDPlayer dvdPlayer;
    private TV tv;
    private Amplifier amplifier;
    private PopcornPopper popcornPopper;

    public HomeTheaterFacade(DVDPlayer dvdPlayer, TV tv, Amplifier amplifier, PopcornPopper popcornPopper) {
        this.dvdPlayer = dvdPlayer;
        this.tv = tv;
        this.amplifier = amplifier;
        this.popcornPopper = popcornPopper;
    }

    public void watchMovie(String movie) {
        System.out.println("准备观看电影 " + movie);
        popcornPopper.on();
        popcornPopper.pop();
        dvdPlayer.on();
        dvdPlayer.playMovie(movie);
        tv.on();
        tv.setChannel(1); // 假设频道1是HDMI输入
        amplifier.on();
        amplifier.setVolume(5);
    }

    public void endMovie() {
        System.out.println("电影结束,关闭所有设备...");
        popcornPopper.off();
        dvdPlayer.off();
        tv.off();
        amplifier.off();
    }
}

3、使用外观模式

最后,在主程序中使用这个外观模式:

java 复制代码
public class HomeTheaterTestDrive {
    public static void main(String[] args) {
        DVDPlayer dvdPlayer = new DVDPlayer("DVD播放机");
        TV tv = new TV("电视机");
        Amplifier amplifier = new Amplifier("音响");
        PopcornPopper popcornPopper = new PopcornPopper("爆米花机");

        HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvdPlayer, tv, amplifier, popcornPopper);

        homeTheater.watchMovie("Matrix");
        homeTheater.endMovie();
    }
}

4、详细解释

在这个家庭影院系统中,我们有四个主要的组件:DVD播放机、电视机、立体声音响以及爆米花机。每个组件都有自己的开关、播放等功能。如果我们想要看一部电影,我们需要分别操作这些设备,这可能会很麻烦。因此,我们创建了一个HomeTheaterFacade类来简化这个过程。
HomeTheaterFacade类充当了客户端和子系统之间的中介者,它负责协调子系统中的各个部分,以便客户端可以通过一个简单的接口来控制整个家庭影院系统。这样做的好处是显而易见的:首先,客户端的代码变得更简单,因为它们只需要与一个对象打交道;其次,如果未来需要更改子系统的行为,只需要修改HomeTheaterFacade类,而不需要改动客户端代码。

四、扩展

在现实世界的应用中,外观模式是非常有用的。例如,在一个大型企业级应用程序中,可能有许多不同的模块和服务,每个模块都有一组复杂的API。对于外部用户来说,直接使用这些API可能是困难的。这时候就可以使用外观模式来提供一个友好的接口,使得外部用户可以更容易地使用这些服务。

此外,外观模式还可以用来实现分层的设计。例如,在一个Web应用程序中,前端页面可能需要从多个后端服务获取数据。通过创建一个外观层,可以将这些服务的调用抽象化,使得前端页面只需要与一个统一的服务接口进行交互,而不需要关心具体的数据是从哪里来的。

五、总结

外观模式过提供一个统一的接口来简化对多个子系统的调用,从而使得系统的使用变得更加容易。在实际项目中,您可以根据需要扩展更多子系统以及它们的功能,从而减少代码的复杂度和长度。

相关推荐
KATA~3 分钟前
解决MyBatis-Plus枚举映射错误:No enum constant问题
java·数据库·mybatis
xyliiiiiL18 分钟前
一文总结常见项目排查
java·服务器·数据库
shaoing20 分钟前
MySQL 错误 报错:Table ‘performance_schema.session_variables’ Doesn’t Exist
java·开发语言·数据库
腥臭腐朽的日子熠熠生辉1 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian1 小时前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码2 小时前
Spring Task 定时任务
java·前端·spring
俏布斯2 小时前
算法日常记录
java·算法·leetcode
27669582922 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息2 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring