设计模式之外观模式

设计模式中的外观模式(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应用程序中,前端页面可能需要从多个后端服务获取数据。通过创建一个外观层,可以将这些服务的调用抽象化,使得前端页面只需要与一个统一的服务接口进行交互,而不需要关心具体的数据是从哪里来的。

五、总结

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

相关推荐
公贵买其鹿2 分钟前
List深拷贝后,数据还是被串改
java
思忖小下9 分钟前
梳理你的思路(从OOP到架构设计)_设计模式Template Method模式
设计模式·模板方法模式·eit
xlsw_3 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹4 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫5 小时前
泛型(2)
java
超爱吃士力架5 小时前
邀请逻辑
java·linux·后端
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石5 小时前
12/21java基础
java
李小白665 小时前
Spring MVC(上)
java·spring·mvc