当前位置: 首页 > news >正文

23种设计模式(10)——门面模式

门面模式(Facade Pattern)又叫作外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型设计模式。

其实,在日常编码工作中,我们都在有意无意地大量使用门面模式。但凡只要高层模块需要调度多个子系统(2个以上类对象),我们都会自觉地创建一个新类封装这些子系统,提供精简的接口,让高层模块可以更加容易地间接调用这些子系统的功能。

来个简单的demo:

我u有以下三个service:

public class ServiceA { public void doA(){ System.out.println("do ServiceA"); } 
} 
public class ServiceB { public void doB(){ System.out.println("do ServiceB"); } 
} public class ServiceC { public void doC(){ System.out.println("do ServiceC"); } 
} 

在没有引入门面模式的时候,我们是这么调用的:

public class Client { public static void main(String[] args) { ServiceA serviceA = new ServiceA(); ServiceB serviceB = new ServiceB(); ServiceC serviceC = new ServiceC(); serviceA.doA(); serviceB.doB(); serviceC.doC(); } 
} 

没啥毛病啊,结合到spingmvc开发,这些service交给spring管理,根本不用自己new了,直接注入到controller就可以,但是如果10个地方都用了这三个service呢?这10个controller里都注入一下?这时候考虑优化——我可以新建一个service,持有这个三个service不就ok了吗:

public class ServiceFacade { //是不是很像我们controller里注入各种service? private ServiceA serviceA = new ServiceA(); private ServiceB serviceB = new ServiceB(); private ServiceC serviceC = new ServiceC(); public void doA() { serviceA.doA(); } public void doB() { serviceB.doB(); } public void doC() { serviceC.doC(); } 
} 

客户端就变成了

public class Client { public static void main(String[] args) { //轻轻松松的搞定,只需要创建门面这个对象即可 ServiceFacade serviceFacade= new ServiceFacade (); serviceFacade.doA(); serviceFacade.doB(); serviceFacade.doC(); } 
} 

门面模式中的角色

由上图可以看到,门面模式主要包含2个角色。

  • 外观角色(Facade):也叫作门面角色,是系统对外的统一接口。
  • 子系统角色(Service):可以同时有一个或多个Service。每个Service都不是一个单独的类,而是一个类的集合。Service们并不知道Facade的存在,对于Service们而言,Facade 只是另一个客户端而已(即Facade对ServiceA、ServiceB、ServiceC透明)。

门面模式的扩展

优点

● 减少系统的相互依赖   想想看,如果我们不使用门面模式,外界访问直接深入到子系统内部,相互之间是一种强耦合关系,你死我就死,你活我才能活,这样的强依赖是系统设计所不能接受的,门面模式的出现就很好地解决了该问题,所有的依赖都是对门面对象的依赖,与子系统无关。

● 提高了灵活性   依赖减少了,灵活性自然提高了。不管子系统内部如何变化,只要不影响到门面对象,任你自由活动。

● 提高安全性   想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到 。

缺点

当增加子系统和扩展子系统行为时,可能容易带来未知风险。

不符合开闭原则。

某些情况下,可能违背单一职责原则。

相关文章:

  • 在Go中处理时间数据
  • Knife4j使用教程(一) -- 在不同版本SpringBoot,选用不同的Knife4j相关的jar包
  • Linux系统之file命令的基本使用
  • Google单元测试sample分析(一)
  • elementUI 特定分辨率(如1920*1080)下el-row未超出一行却换行
  • Python深度学习实战-基于tensorflow原生代码搭建BP神经网络实现分类任务(附源码和实现效果)
  • Python:实现日历到excel文档
  • html5怎么实现语音搜索
  • SOLIDWORKS PDM 2024数据管理5大新功能
  • 制作自己的前端组件库并上传到npm上
  • 互动直播UI设置 之 主播UI
  • 【java学习—十】HashSet集合(4)
  • C++之左值、右值、std::forward、std::move总结(二百五十)
  • 禁用Google Chrome自动升级、查看Chrome版本号
  • pythonWeb主流框架分析
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • JavaScript-Array类型
  • javascript从右向左截取指定位数字符的3种方法
  • Java比较器对数组,集合排序
  • Java深入 - 深入理解Java集合
  • jQuery(一)
  • JS笔记四:作用域、变量(函数)提升
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • React的组件模式
  • RxJS: 简单入门
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • TypeScript迭代器
  • win10下安装mysql5.7
  • 从零开始的无人驾驶 1
  • 大整数乘法-表格法
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 原生Ajax
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 字符串匹配基础上
  • 1.Ext JS 建立web开发工程
  • scrapy中间件源码分析及常用中间件大全
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (二)windows配置JDK环境
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (转)关于pipe()的详细解析
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)OpenStack Hacker养成指南
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .net 4.0发布后不能正常显示图片问题
  • .Net 垃圾回收机制原理(二)
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .NET分布式缓存Memcached从入门到实战