设计模式学习笔记 - 外观模式
设计模式学习笔记 - 外观模式
- 一、影院管理问题
- 二、传统方式解决影院管理问题
- 三、外观模式介绍
- 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机试 - 组成最大数…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...