设计模式学习笔记 - 外观模式
设计模式学习笔记 - 外观模式
- 一、影院管理问题
- 二、传统方式解决影院管理问题
- 三、外观模式介绍
- 1、基本介绍
- 2、原理类图
- 四、外观模式解决影院管理问题
- 五、外观模式在MyBatis框架应用的源码分析
- 六、外观模式的注意事项和细节
一、影院管理问题
组建一个家庭影院:DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机。要求完成使用家庭影院的功能,其过程为直接用遥控器统筹各设备开关:
1.打开爆米花机
2.放下屏幕
3.打开投影仪
4.打开音响
5.打开DVD,选dvd
6.去拿爆米花
7.调暗灯光
8.播放dvd
9.观影结束后,关闭各种设备
二、传统方式解决影院管理问题
-
类图:

-
传统方式解决影院管理问题分析:
(1)在 Client的main方法中,创建各个子系统的对象,并直接去调用子系统(对象)相关方法,会造成调用过程混乱,没有清晰的过程。在Client中不利于去维护对子系统的操作。
(2)解决思路:定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比如在高层接口中提供四个方法on、play、pause、off),用来访问子系统中的一群接口。也就是说,通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,使得调用端只需跟这个一致的接口发生调用,而无需关心这个子系统的内部细节。这就是使用了外观模式。
三、外观模式介绍
1、基本介绍
外观模式(Facade Pattern),也叫“过程模式”。外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节。
外观模式可以理解为转换一群接口,客户只要调用一个接口,而不用调用多个接口才能达到目的。
外观模式就是解决多个复杂接口带来的使用困难,起到简化用户操作的作用。
2、原理类图

说明:
- 外观类(Facade):为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象。
- 子系统的集合:指模块或者子系统,处理Facade对象指派的任务,是功能实际提供者。
- 调用者(Client):外观接口的调用者。
四、外观模式解决影院管理问题
-
类图:

-
实现代码:
package com.etc.design.facade;public class Client {public static void main(String[] args) {// 使用外观类实现过程HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();// 开启所有设备homeTheaterFacade.ready();// DVD播放homeTheaterFacade.play();// DVD暂停homeTheaterFacade.pause();// 关闭所有设备homeTheaterFacade.end();}
}
package com.etc.design.facade;/*** 外观类*/
public class HomeTheaterFacade {//定义各个子系统对象private TheaterLight theaterLight;private Popcorn popcorn;private Stereo stereo;private Projector projector;private Screen screen;private DVDPlayer dVDPlayer;//构造器public HomeTheaterFacade() {super();this.theaterLight = TheaterLight.getInstance();this.popcorn = Popcorn.getInstance();this.stereo = Stereo.getInstance();this.projector = Projector.getInstance();this.screen = Screen.getInstance();this.dVDPlayer = DVDPlayer.getInstanc();}// 操作分成4步public void ready() {System.out.println("-----开启所有设备-----");popcorn.on();popcorn.pop();screen.down();projector.on();stereo.on();dVDPlayer.on();theaterLight.dim();}public void play() {System.out.println("-----播放DVD-----");dVDPlayer.play();}public void pause() {System.out.println("-----暂停DVD-----");dVDPlayer.pause();}public void end() {System.out.println("-----关闭所有设备-----");popcorn.off();theaterLight.bright();screen.up();projector.off();stereo.off();dVDPlayer.off();}
}
package com.etc.design.facade;public class DVDPlayer {// 使用用饿汉单例模式private static DVDPlayer instance = new DVDPlayer();public static DVDPlayer getInstanc() {return instance;}public void on() {System.out.println(" DVD on ");}public void off() {System.out.println(" DVD off ");}public void play() {System.out.println(" DVD play ");}public void pause() {System.out.println(" DVD pause ");}
}
package com.etc.design.facade;public class Popcorn {// 使用用饿汉单例模式private static Popcorn instance = new Popcorn();public static Popcorn getInstance() {return instance;}public void on() {System.out.println(" popcorn on ");}public void off() {System.out.println(" popcorn ff ");}public void pop() {System.out.println(" popcorn is poping ");}
}
package com.etc.design.facade;public class Projector {// 使用用饿汉单例模式private static Projector instance = new Projector();public static Projector getInstance() {return instance;}public void on() {System.out.println(" Projector on ");}public void off() {System.out.println(" Projector ff ");}public void focus() {System.out.println(" Projector is Projector ");}
}
package com.etc.design.facade;public class Screen {// 使用用饿汉单例模式private static Screen instance = new Screen();public static Screen getInstance() {return instance;}public void up() {System.out.println(" Screen up ");}public void down() {System.out.println(" Screen down ");}
}
package com.etc.design.facade;public class Stereo {// 使用用饿汉单例模式private static Stereo instance = new Stereo();public static Stereo getInstance() {return instance;}public void on() {System.out.println(" Stereo on ");}public void off() {System.out.println(" Stereo off ");}public void up() {System.out.println(" Stereo up ");}public void down() {System.out.println(" Stereo down ");}
}
package com.etc.design.facade;public class TheaterLight {// 使用用饿汉单例模式private static TheaterLight instance = new TheaterLight();public static TheaterLight getInstance() {return instance;}public void on() {System.out.println(" TheaterLight on ");}public void off() {System.out.println(" TheaterLight off ");}public void dim() {System.out.println(" TheaterLight dim ");}public void bright() {System.out.println(" TheaterLight bright ");}
}

五、外观模式在MyBatis框架应用的源码分析
MyBatis中的Configuration去创建MetaObject对象使用到外观模式。
- 类图:

- 源码:
package org.apache.ibatis.session;
......
public class Configuration {......protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();protected ObjectFactory objectFactory = new DefaultObjectFactory();protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();......public MetaObject newMetaObject(Object object) {return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);}......
}
package org.apache.ibatis.reflection;
......
public class MetaObject {private Object originalObject;private ObjectWrapper objectWrapper;private ObjectFactory objectFactory;private ObjectWrapperFactory objectWrapperFactory;private ReflectorFactory reflectorFactory;private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {this.originalObject = object;this.objectFactory = objectFactory;this.objectWrapperFactory = objectWrapperFactory;this.reflectorFactory = reflectorFactory;if (object instanceof ObjectWrapper) {this.objectWrapper = (ObjectWrapper) object;} else if (objectWrapperFactory.hasWrapperFor(object)) {this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);} else if (object instanceof Map) {this.objectWrapper = new MapWrapper(this, (Map) object);} else if (object instanceof Collection) {this.objectWrapper = new CollectionWrapper(this, (Collection) object);} else {this.objectWrapper = new BeanWrapper(this, object);}}......public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {if (object == null) {return SystemMetaObject.NULL_META_OBJECT;} else {return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);}}......
}
package org.apache.ibatis.reflection.factory;public interface ObjectFactory {......
}
package org.apache.ibatis.reflection.factory;public class DefaultObjectFactory implements ObjectFactory, Serializable {......
}
package org.apache.ibatis.reflection.wrapper;public interface ObjectWrapperFactory {......
}
package org.apache.ibatis.reflection.wrapper;public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {......
}
六、外观模式的注意事项和细节
(1)外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性。
(2)外观模式对客户端与子系统的耦合关系进行解耦,让子系统内部的模块更易维护和扩展。
(3)通过合理的使用外观模式,可以更好的划分访问的层次。
(4)当系统需要进行分层设计时,可以考虑使用外观模式。
(5)在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade类交互,提高复用性。
(6)不能过多的或者不合理的使用外观模式。如果子系统模块过于复杂,可以使用外观模式进行分层。如果子系统模块比较简单,可以直接调用模块。要以让系统有层次,利于维护为目的。
相关文章:
设计模式学习笔记 - 外观模式
设计模式学习笔记 - 外观模式一、影院管理问题二、传统方式解决影院管理问题三、外观模式介绍1、基本介绍2、原理类图四、外观模式解决影院管理问题五、外观模式在MyBatis框架应用的源码分析六、外观模式的注意事项和细节一、影院管理问题 组建一个家庭影院:DVD 播放…...
如何写出一份优秀的简历和求职信?
写一份优秀的简历和求职信是成功求职的重要一步。 01、简历 突出重点信息:把最重要的信息放在简历的前面,例如您的工作经验和教育背景等。 使用简明扼要的语言:在简历中使用简短的句子和简明扼要的语言,让招聘者能够快速了解您的…...
OpenGL超级宝典学习笔记:原子计数器
前言 本篇在讲什么 本篇为蓝宝书学习笔记 原子计数器 本篇适合什么 适合初学Open的小白 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践,轻理论&#…...
深圳/东莞/惠州师资比较强的CPDA数据分析认证
深圳/东莞/惠州师资比较强的CPDA数据分析认证培训机构 CPDA数据分析师认证是中国大数据领域有一定权威度的中高端人才认证,它不仅是中国较早大数据专业技术人才认证、更是中国大数据时代先行者,具有广泛的社会认知度和权威性。 无论是地方政府引进人才、…...
LeetCodeHOT100热题02
写在前面 主要是题目太多,所以和前面的分开来记录。有很多思路的图都来源于力扣的题解,如侵权会及时删除。不过代码都是个人实现的,所以有一些值得记录的理解。之前的算法系列参看: 剑指offer算法题01剑指offer算法题02 七、动…...
虹科Dimetix激光测距仪在锯切系统中的应用
HK-Dimetix激光测距仪——锯切系统应用 许多生产设施,例如金属服务中心,使用切割锯将每个客户的订单切割成一定长度。定长切割过程通常涉及卷尺和慢跑锯的传送带。但更简单的替代方法是使用虹科Dimetix非接触式激光距离传感器。 为了切断大长度的棒材&…...
FreeRTOS入门(02):任务基础使用与说明
文章目录目的创建任务任务调度任务控制延时函数任务句柄获取与修改任务优先级删除任务挂起与恢复任务强制任务离开阻塞状态空闲任务总结目的 任务(Task)是FreeRTOS中供用户使用的最核心的功能,本文将介绍任务创建与使用相关的基础内容。 本…...
ESP通过乐为物联控制灯,微信发送数值,ESP上传传感器数据
暂时放个程序 //ME->>{“method”: “update”,“gatewayNo”: “01”,“userkey”: “2b64c489d5f94237bcf2e23151bb7d01”}&^! //Ser->>{“f”:“message”,“p1”:“ok”}&^! //ME->>{“method”: “upload”,“data”:[{“Name”:“A1C”,“Val…...
Linux:共享内存api使用
代码: #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h> #include <sys/un.h> #include <sys/ipc.h…...
android9.0 java静态库操作JNI实例 动态注册
一、java层 源码 目录:/Demo/java/com/android/simpleini/SimpleJNI.java package com.example.simplejni;import android.app.Activity; import android.os.Bundle; import android.widget.TextView;public class SimpleJNI {private IpoManagerService(Context …...
自定义复杂图片水印
我的社交能力还不如5岁儿童和狗。 文章目录前言一、主要工具类总结前言 之前写过一些简单的图片压缩和图片加水印:JAVA实现图片质量压缩和加水印 本次主要是针对图片加水印进行一个升级,图片水印自定义,自适应大小。 来,先看几…...
文章读后感——《人间清醒,内容为王》
观后感 人间清醒,内容为王 - 技术er究竟该如何写博客?1024上海嘉年华之敖丙演讲观后感。 致敬愿意带领后生的前辈——哈哥 哈哥,《人间清醒,内容为王》这篇,我的鱼获, 是里面传递出来写技术博客的思维与想法…...
51单片机入门 - 驱动多位数码管
我使用的是普中51单片机开发板A2套件(2022),驱动数码管可能需要参考电路原理图。开发环境的搭建教程在本专栏的 51单片机开发环境搭建 - VS Code 从编写到烧录 有过介绍。 关于我的软硬件环境信息: Windows 10STC89C52RCSDCC &am…...
Java进击框架:Spring(一)
Java进击框架:Spring(一)前言创建Spring项目Spring IoC容器和Beans介绍Bean的概述Spring IoC配置元数据实例化Bean依赖注入循环依赖详细配置生命周期回调Bean定义继承基于注解的容器配置Component和进一步的原型注解自动检测类和注册Bean定义…...
Java笔记(18)
目录 什么是mvc? 什么是SpringMVC Spring MVC的特点: 原理: 什么是Thymeleaf? thymeleaf依赖包:...
【免费教程】地下水环境监测技术规范HJ/T164-2020解读使用教程
地下水环境监测技术规范依据《中华人民共和国环境保护法》第十一条“国务院环境保护行政主管部门建立监测制度、制订监测规范”和《中华人民共和国水污染防治法》的要求,积极开展地下水环境监测,掌握地下水环境质量,保护地下水水质࿰…...
Html 代码学习
场景:在页面中插入音频 代码 常见属性: src 音频的路径 controls 显示播放的控件 autoplay 自动播放 loop 循环播放 场景:在页面中插入视频 代码 常见属性: src 路径 controls 显示播放的控件 autoplay 自动播放 要配合muted 例如 autoplay muted loop 循环播放 链接 /…...
如何通过IP找到地址?
在我们印象中,我们都知道可以通过 IP 地址找到某个人。但当我们细想一下,我们会发现其实 IP 地址与地理位置并不是直接相关的。那我们到底是如何通过 IP 地址找到地址的呢?答案是:通过自治系统(Autonomous System&…...
业务单据堆积如山?如何提升会计做账效率?
某集团以“创建现代能源体系、提高人民生活品质”为使命,形成了贯通下游分销、中游贸易储运、上游生产的清洁能源产业链和涵盖健康、文化、旅游、置业的生命健康产品链。目前,某集团在全国21个省,为超过2681万个家庭用户、21万家企业提供能源…...
华为OD机试题,用 Java 解【VLAN 资源池】问题
最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
