设计模式之Facade设计模式

news2024/11/13 9:42:13

Facade设计模式,也称为外观模式,是一种结构型设计模式,它主要用于为子系统中的一组接口提供一个统一的高层接口,从而使得子系统更加容易使用。以下是关于Facade设计模式的详细介绍:

一、定义

Facade模式为多个复杂的子系统提供一个对外的接口,使得这些子系统更加容易地被访问。该模式对外有一个统一的接口,外部应用无需关心子系统内部的细节,从而大大降低了应用程序的复杂度,提高了可维护性。

二、动机与目的

  • 降低复杂性:通过将子系统的复杂性封装在Facade类中,客户端可以通过简单的接口来调用子系统,而无需深入了解子系统的具体实现。
  • 提高易用性:Facade模式提供了一个简单的接口,使得客户端可以更容易地使用子系统。
  • 松散耦合:通过引入Facade类,降低了客户端与子系统之间的耦合度,使得子系统内部的变化不会影响到客户端。

三、结构与类图

类图:

Facade模式主要包含以下三个角色:

  • Facade(外观角色):客户端可以调用这个角色的方法。外观类知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
  • Subsystem(子系统角色):可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被外观角色调用。子系统并不知道外观的存在,对于子系统而言,外观仅仅是另外一个客户端而已。
  • Client(客户端角色):用户通过外观类调用子系统的功能。

四、优缺点

优点
  1. 降低系统的复杂性:通过为子系统提供一个简单的接口,使得客户端更容易理解和使用系统。
  2. 提高系统的灵活性:当子系统内部发生变化时,只需要修改Facade类即可,而不需要修改客户端代码。
  3. 符合迪米特法则:通过引入Facade类,减少了客户端与子系统之间的依赖关系。
缺点
  1. 增加子系统或扩展子系统行为容易引入风险:因为所有的请求都需要通过Facade类进行转发,如果Facade类设计不当,可能会引入新的风险。
  2. 不符合开闭原则:在某些情况下,如果需要对系统进行扩展,可能需要修改Facade类的代码,这违反了开闭原则(即对扩展开放,对修改关闭)。

五、应用场景

  • 当系统需要对外提供一个简单的接口时,可以使用Facade模式。
  • 当系统需要隐藏子系统的复杂性时,可以使用Facade模式。
  • 当需要构建一个多层系统结构时,可以利用Facade对象作为每层的入口,简化层级调用。

六、实现例子

在家庭影院系统中,可以使用Facade模式来简化用户的操作。例如,用户只需要使用一个遥控器(Facade类)就可以控制投影仪、音响、DVD机等设备(子系统),而无需分别操作这些设备。

// 投影仪接口  
interface Projector {  
    void on();  
    void off();  
    void focus();  
    void wideScreenMode();  
}  
  
// 投影仪实现类  
class SimpleProjector implements Projector {  
    @Override  
    public void on() {  
        System.out.println("Projector is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("Projector is off");  
    }  
  
    @Override  
    public void focus() {  
        System.out.println("Adjusting projector focus");  
    }  
  
    @Override  
    public void wideScreenMode() {  
        System.out.println("Switching to wide screen mode");  
    }  
}  
  
// DVD播放器接口  
interface DVDPlayer {  
    void on();  
    void off();  
    void play();  
    void stop();  
    void pause();  
    void eject();  
    void setTwoChannelAudio();  
    void setSurroundAudio();  
}  
  
// DVD播放器实现类  
class SimpleDVDPlayer implements DVDPlayer {  
    @Override  
    public void on() {  
        System.out.println("DVD Player is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("DVD Player is off");  
    }  
  
    @Override  
    public void play() {  
        System.out.println("DVD Player is playing");  
    }  
  
    @Override  
    public void stop() {  
        System.out.println("DVD Player stopped");  
    }  
  
    @Override  
    public void pause() {  
        System.out.println("DVD Player paused");  
    }  
  
    @Override  
    public void eject() {  
        System.out.println("DVD ejected");  
    }  
  
    @Override  
    public void setTwoChannelAudio() {  
        System.out.println("Stereo mode is on");  
    }  
  
    @Override  
    public void setSurroundAudio() {  
        System.out.println("Surround sound mode is on");  
    }  
}  
  
// 音响接口  
interface Amplifier {  
    void on();  
    void off();  
    void setStereoSound();  
    void setSurroundSound();  
    void setVolume(int volume);  
}  
  
// 音响实现类  
class StereoAmplifier implements Amplifier {  
    @Override  
    public void on() {  
        System.out.println("Amplifier is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("Amplifier is off");  
    }  
  
    @Override  
    public void setStereoSound() {  
        System.out.println("Stereo mode is on");  
    }  
  
    @Override  
    public void setSurroundSound() {  
        System.out.println("Surround sound mode is on");  
    }  
  
    @Override  
    public void setVolume(int volume) {  
        System.out.println("Setting volume to " + volume);  
    }  
}  
  
// 家庭影院Facade类  
class HomeTheaterFacade {  
    private Projector projector;  
    private DVDPlayer dvdPlayer;  
    private Amplifier amplifier;  
  
    public HomeTheaterFacade(Projector projector, DVDPlayer dvdPlayer, Amplifier amplifier) {  
        this.projector = projector;  
        this.dvdPlayer = dvdPlayer;  
        this.amplifier = amplifier;  
    }  
  
    // 提供一个简单的方法来观看电影  
    public void watchMovie(String movie) {  
        System.out.println("Get ready to watch a movie...");  
  
        projector.on();  
        projector.wideScreenMode();  
  
        amplifier.on();  
        amplifier.setSurroundSound();  
        amplifier.setVolume(5);  
  
        dvdPlayer.on();  
        dvdPlayer.play(movie);  
  
        System.out.println("Enjoy the movie...");  
    }  
  
    // 提供一个简单的方法来结束观看  
    public void endMovie() {  
        System.out.println("Shutting movie theater down...");  
  
        projector.off();  
        amplifier.off();  
        dvdPlayer.stop();  
        dvdPlayer.eject();  
        dvdPlayer.off();
    }
}
        
class Client{
    public static void main(String[] args) { 
        Projector projector = new SimpleProjector();
        DVDPlayer dvdPlayer = new SimpleDVDPlayer();
        Amplifier amplifier = new StereoAmplifier();
        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(projector,dvdPlayer,amplifier);
        homeTheaterFacade.watchMovie("肖申克的救赎");
        homeTheaterFacade.endMovie();
    }
}

这个例子中可以看到facade模式,特别适用于使用多个组件,组装固定流程,降低客户端的调用复杂度。

七、总结

Facade设计模式是一种非常实用的设计模式,它通过为子系统提供一个统一的接口来降低系统的复杂性、提高系统的易用性和灵活性。然而,在使用该模式时也需要注意其可能带来的缺点和风险。

如果这个模式对你有用,记得点赞收藏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911830.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库MySQL---基础篇

存储和管理数据的仓库 MySQL概述 数据库相关概念 数据库(DataBase)---数据存储的仓库,数据是有组织的进行存储 数据库管理系统(DBMS)-----操纵和管理数据库的大型软件 SQL----操作关系型数据库的编程语言&#xff…

C++之goto陈述

关键字 goto用于控制程式执行的顺序&#xff0c;使程式直接跳到指定标签(lable) 的地方继续执行。 形式如下 标签可以是任意的识别字&#xff0c;后面接一个冒号。 举例如下 #include <iostream>int main() {goto label_one;label_one: {std::cout << "Lab…

0302GPIO外设输入功能

GPIO外设输入功能 输入部分硬件电路按键简介传感器模块简介按键和传感器模块的硬件电路 C语言的学习C语言数据类型宏定义typedef结构体枚举C语言知识总结 按键控制LED灯&光敏传感器蜂鸣器GPIO总结GPIO使用方法总结模块化编程的方法&#xff1a; 两个程序&#xff1a;按键控…

Error:sql: expected 1 arguments, got 2

一 背景 在测试一个API接口时&#xff0c;看到日志里面突然抛出一个错误&#xff1a;Error:sql: expected 1 arguments, got 2 看了下&#xff0c;对应的表里面是有相关数据的&#xff0c;sql语句放在mysql里面执行也是没问题&#xff01;那奇了怪了&#xff0c;为啥会产生这样…

【MindSpore学习打卡】应用实践-热门LLM及其他AI应用-使用MindSpore实现K近邻算法对红酒数据集进行聚类分析

在机器学习领域&#xff0c;K近邻算法&#xff08;K-Nearest Neighbor, KNN&#xff09;是最基础且常用的算法之一。无论是分类任务还是回归任务&#xff0c;KNN都能通过简单直观的方式实现高效的预测。在这篇博客中&#xff0c;我们将基于MindSpore框架&#xff0c;使用KNN算法…

alibabacloud学习笔记11

讲解什么是配置中心及使用前后的好处 讲解Nacos作为配置中心面板介绍 官方文档 Nacos config alibaba/spring-cloud-alibaba Wiki GitHub 加入依赖&#xff1a; 订单服务和视频服务也加上这个依赖。 讲解Nacos作为配置中心实战 订单服务添加配置。 我们注释掉之前的配置。 …

Java项目:基于SSM框架实现的农家乐信息管理平台含前后台【ssm+B/S架构+源码+数据库+答辩PPT+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的农家乐信息管理平台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

Mybatis Plus 3.X版本的insert填充自增id的IdType.ID_WORKER策略源码分析

总结/朱季谦 某天同事突然问我&#xff0c;你知道Mybatis Plus的insert方法&#xff0c;插入数据后自增id是如何自增的吗&#xff1f; 我愣了一下&#xff0c;脑海里只想到&#xff0c;当在POJO类的id设置一个自增策略后&#xff0c;例如TableId(value "id",type …

Linux多进程和多线程(八)多线程

多线程 线程定义线程与进程线程资源 线程相关命令 pidstat 命令 top 命令ps 命令常见的并发方案 1. 多进程模式2. 多线程模式 创建线程 1. pthread_create() 示例:创建一个线程 2. pthread_exit() 退出线程3. pthread_join() 等待线程结束 示例: 线程分离 创建多个线程 示例 1:…

Spring Boot集成grpc快速入门demo

1.什么是GRPC&#xff1f; gRPC 是一个高性能、开源、通用的RPC框架&#xff0c;由Google推出&#xff0c;基于HTTP2协议标准设计开发&#xff0c;默认采用Protocol Buffers数据序列化协议&#xff0c;支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务&#xff0c…

VUE之旅—day3

工程化开发和脚手架Vue CLI 开发Vue的两种方式&#xff1a; 核心包创痛开发模式&#xff1a;基于html/css/js文件&#xff0c;直接引入核心包&#xff0c;开发Vue。 工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue。…

『大模型笔记』GraphRAG:利用复杂信息进行发现的新方法!

GraphRAG:利用复杂信息进行发现的新方法! 文章目录 一. GraphRAG:利用复杂信息进行发现的新方法!1. 将RAG应用于私人数据集2. 整个数据集的推理3. 创建LLM生成的知识图谱4. 结果指标5. 下一步二. 参考文献微软官方推文:https://www.microsoft.com/en-us/research/blog/gra…

招投标信息采集系统:让您的企业始终站在行业前沿

一、为何招投标信息如此关键&#xff1f; 在经济全球化的大背景下&#xff0c;招投标活动日益频繁&#xff0c;成为企业获取项目、拓展市场的主流方式之一。招投标信息采集&#xff0c;作为企业战略决策的前置环节&#xff0c;其重要性不言而喻。它不仅关乎企业能否第一时间发…

实时消息推送系统,写得太好了!

websocket 协议是在 http 协议上的一种补充协议&#xff0c;是 html5 的新特性&#xff0c;是一种持久化的协议。其实 websocket 和 http 关系并不是很大&#xff0c;不过都是属于应用层的协议&#xff0c;接下来我们就开始实战。 websocket 定时推送 本教程基于 springboot …

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 问题概述 📒📒 解决方案 📒🔖 方法一🔖 方法二🔖 方法三⚓️ 相关链接 🚓️📖 介绍 📖 在群晖(Synology)NAS设备上使用Docker时,我们可能会遇到查询Docker注册表失败,无法拉取Docker镜像的问题。这种情况…

一文理解 Treelite,Treelite 为决策树集成模型的部署和推理提供了高效、灵活的解决方案

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、什么是 Treelite&#xff1f; Treelite 是一个专门用于将决策树集成模型高效部署到生产环境中的机器学习模型编译器&#xff0c;特别适合处理大批量数据的推理任务&#xff0c;能够显著提升推理性能…

《RWKV》论文笔记

原文出处 [2305.13048] RWKV: Reinventing RNNs for the Transformer Era (arxiv.org) 原文笔记 What RWKV(RawKuv):Reinventing RNNs for the Transformer Era 本文贡献如下&#xff1a; 提出了 RWKV 网络架构&#xff0c;结合了RNNS 和Transformer 的优点&#xff0c;同…

vscode调试教程

VSCode调试 VSCode Debuggers VSCode使用launch.json进行细粒度的控制&#xff0c;可以启动程序或将其附加到复杂的调试场景中 打开Run and Debug视图Ctrl Shift D 点击create a launch.json file&#xff0c;选择C(GDB/LLDB) 会在工作目录自动创建.vscode/launch.json文…

单对以太网连接器多场景应用

单对以太网连接器应用场景概述 单对以太网&#xff08;Single Pair Ethernet&#xff0c;简称SPE&#xff09;作为一种新兴的以太网技术&#xff0c;以其独特的优势在多个领域得到了广泛的应用。SPE通过单对电缆进行数据传输&#xff0c;支持高速数据传输&#xff0c;同时还能…

Python学习笔记33:进阶篇(二十二)pygame的使用之image模块

前言 基础模块的知识通过这么长时间的学习已经有所了解&#xff0c;更加深入的话需要通过完成各种项目&#xff0c;在这个过程中逐渐学习&#xff0c;成长。 我们的下一步目标是完成python crash course中的外星人入侵项目&#xff0c;这是一个2D游戏项目。在这之前&#xff…