外观模式 门面模式 Facade 结构型 设计模式(十三)

时间:2022-09-05 14:20:34
外观模式(FACADE)
又称为门面模式
外观模式 门面模式 Facade  结构型 设计模式(十三)
 

意图

为子系统中的一组接口提供一个一致的界面
Facade模式定义了一个高层接口,这一接口使得这一子系统更加易于使用。

意图解析

随着项目的持续发展,系统基本上都是会往功能更全面的方向发展,那么也就意味着我们的系统将会变得更加复杂。
系统会被划分为多个单独的子系统,每个子系统完成一部分功能,通过分工协作完成全部功能。
一个子系统也可能进一步拆分为更小的几个子系统。
 
程序中的文件将会越来越多,相互关联也会变得更加复杂
当使用一个功能的时候,作为客户端
你需要弄清楚相关类之间的关系,以及正确的调用顺序。
 
比如下图中
你需要自己识别有哪些子系统,涉及哪些相关的类和方法,你需要自己保证顺序(如果功能调用依赖顺序的话)
外观模式 门面模式 Facade  结构型 设计模式(十三)
 
如同在医院里面,病人需要自己去排队挂号化验,跟每个流程的工作人员进行协作
如同在工厂里面,需要生产一个桌子,你亲自用机器生产桌子腿,自己使用机器生产桌面...
如同你去其他公司洽谈业务,你单独跟每个相关业务的人员进行联系沟通
 
你肯定想得到,如果有一个中间人为你代劳
不需要面对林林总总的子系统、部门、人员...
当你需要某种服务时,只需要告诉这个中间人就好了
这个想法就是外观模式
外观模式 门面模式 Facade  结构型 设计模式(十三)
 
有了facade,你就不需要跟每个子系统进行单独的交流了
如同在医院里面,对于VIP,有专人代替你挂号.....
如同在工厂里面,有一个控制台机器,你选择产品,控制台下发命令安排其他的机器生产具体产品
如同你去其他公司洽谈业务,有一个接口人负责与你对接,他们那边的事情都通过这个人进行安排
 
外观模式 门面模式 Facade  结构型 设计模式(十三)
 
外观模式的意图含义,如同他的名字一样,“建筑物的正面”
面对一个复杂的大楼,当你在正面远远望去,也就只能看到正面
在外观模式中,形容一个庞大的复杂的系统的一个直观的界面
借助于Facade模式
从原来的“客户端需要跟多个子系统进行交互”,转变为“只与Facade进行交互”
将客户端与子系统进行解耦,降低了耦合性,也降低了使用的复杂度

代码示例

“关好门窗,防火防盗”这句话有没有听过?
回想一下,当你早上准备出门离开家时,你会做什么?
假设你会关水、关灯、关门窗。
我们创建三个类,水 灯 窗,模拟离开家的场景  
package facade;
public class Water {
public void turnOn() {
System.out.println("打开水龙头...");
}
public void turnOff() {
System.out.println("关闭水龙头...");
}
}
package facade;
public class Light {
public void turnOn() {
System.out.println("开灯...");
}
public void turnOff() {
System.out.println("关灯...");
}
}
package facade;

public class Window {
public void open() {
System.out.println("开窗...");
}
public void close() {
System.out.println("关窗...");
}
}
测试代码
外观模式 门面模式 Facade  结构型 设计模式(十三)
 
上面的测试代码Test作为客户端程序,可以看得出来,他直接跟Water Light Window三个类的对象进行交互
他需要调用相关的方法
也就是说Test 作为客户端对于“离家”这一系统的内部逻辑是了如指掌的--->需要断水、关灯、关窗
他也清楚每个类的方法
一方面增加了耦合性,另一方面将子系统的内部细节暴露出来

优化重构

试想下,如果你家是智能家居,有一个控制台Facade,或者说有一个手机App
他可以控制整个家庭的设备
package facade;

public class Facade {
private Water water = new Water();
private Light light = new Light();
private Window window = new Window(); public void leaveHome(){
water.turnOff();
light.turnOff();
window.close();
} public void backHome(){
light.turnOn();
window.open();
} }
外观模式 门面模式 Facade  结构型 设计模式(十三)
 
通过这个控制台,客户端程序不再需要了解子系统的内部细节,他也不清楚每个类到底有哪些方法
所有的交互都是通过Facade来完成的

结构

外观模式 门面模式 Facade  结构型 设计模式(十三)
Facade 外观角色
客户端调用角色,知晓子系统的所有功能与职责
通常,Facade会将所有的请求转发委派到子系统中去,也就是说该角色没有实际的业务、
 
SubSystem子系统角色
可以同时有一个或者多个子系统
注意   :子系统并不是说一个单独的类,而是一个类的集合,这些类根据逻辑功能点被组织在一起  
子系统并不知道Facade的存在,对于子系统来说,Facade也就只是一个客户端程序
 
外观模式的结构比较简单,类似一个“封装”提取的过程
他的根本原则为迪米特法则,也就是“不要和陌生人说话”,尽可能少的与其他的对象进行交互
通过外观模式,做到了子系统只与外观对象交互
 
门面类个数
在门面模式中,通常只需要一个门面类,并且这个门面类只有一个实例
换句话说他很可能是一个单例
但是并不是说整个系统中只能有一个门面类
门面类的个数要根据系统中子系统的个数以及业务逻辑的情况

总结

当你需要为一个复杂的子系统提供一个简单的接口时或者希望子系统能够更加独立时,可以考虑使用外观模式
借助于外观模式,可以实现客户端与子系统的解耦,减少客户端对子系统的依赖性
一旦完成解耦,就意味着子系统有良好的独立性,也能拥有更好的扩展性
因为独立了,就意味着单独的子系统修改不会影响其他系统
而且,在多层次结构的系统中,可以使用Facade模式进行层与层之间的交互,将层与层之间的耦合性降低,使他们仅仅通过facade进行交互
总之一句话,降低了使用子系统的复杂程度,降低了耦合程度,满足迪米特法则----不要和陌生人说话 
对客户端屏蔽了子系统的组件
仅仅通过Facade,大大减少了客户端所需要处理的对象的数目
对于外观模式,如果是子系统发生变化,Facade则极有可能需要面临修改,这不符合开闭原则 
外观模式(门面模式)就如同我们开篇的图片一样,作为公司前台
接待来访宾客,一切事宜都有她来协调安排组织。
在OOP中,这个“前台”不仅是一个子系统的“正面”看到的样子,而且还强调了她的全权负责
她提供所有的业务需要的相关方法,尽管内部调用都是子系统中的方法,她提供简单一致的交流沟通形式 
理解了迪米特法则,那么就比较容易理解外观模式
外观模式重点在于提供一个“简化”“封装”后的操作控制台,让你更容易操作整个系统,他几乎不会涉及子系统的内部逻辑
否则,门面对象将与子系统的业务逻辑耦合,增加了耦合度。
 

外观模式 门面模式 Facade 结构型 设计模式(十三)的更多相关文章

  1. OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式

    前言 前面我们学习了创建型设计模式,其中有5中,个人感觉比较重要的是工厂方法模式.单例模式.原型模式.接下来我将分享的是结构型模式! 一.适配器模式 1.1.适配器模式概述 适配器模式(Adapter ...

  2. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  3. 代理模式 PROXY Surrogate 结构型 设计模式(十四)

    代理模式 PROXY 别名Surrogate 意图 为其他的对象提供一种代理以控制对这个对象的访问. 代理模式含义比较清晰,就是中间人,中介公司,经纪人... 在计算机程序中,代理就表示一个客户端不想 ...

  4. 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)

      桥接模式Bridge   Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来   意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展.  意图解析 依赖倒置原 ...

  5. 组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)

    组合模式(合成模式 COMPOSITE) 意图 将对象组合成树形结构以表示“部分-整体”的层次结构. Composite使得用户对单个对象和组合对象的使用具有一致性.   树形结构介绍 为了便于理解, ...

  6. 设计模式 | 外观模式/门面模式(facade)

    定义: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 结构:(书中图,侵删) 一个简洁易用的外观类 一个复杂的子系统   实例: 书中提到了理 ...

  7. 享元模式/Flyweight模式/对象结构型/设计模式

    flyweight 享元模式(对象结构型) Flyweight在拳击比赛中指最轻量级,即"蝇量级"或"雨量级",这里选择使用"享元模式"的意 ...

  8. java设计模式——外观模式(门面模式)

    一. 定义与类型 定义:门面模式,提供一个统一的接口,用来访问子系统中的一群接口,门面模式定义了一个高层接口,让子系统更容易使用 类型:结构性 二. 使用场景 子系统越来越复杂,增加外观模式提供简单调 ...

  9. 12、Decorator 装饰器 模式 装饰起来美美哒 结构型设计模式

    1.Decorator模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式(Decorator Pattern)允许向一个现 ...

随机推荐

  1. 【从零开始学BPM,Day5】报表配置及自定义功能页面开发

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间*安排. [第五天课程] 1.课程概要 Step 1 软件下载:H3 BP ...

  2. 第一章	DeepLab的创作动机

    这一段时间一直在做深度学习方面的研究,目前市场上的深度学习工具主要分为两大块.一块是基于Python语言的theano:另一块是可以在多个语言上使用并能够在GPU和CPU之间随意切换的Caffe.但是 ...

  3. writel(readl(&pwm_timer->tcfg0) | 0xff, &pwm_timer->tcfg0);

    解析这句代码什么意思! 神说:选定预分频器0 为什么? 神说:因为实验中选的是timer1,在预分频器0下: 若选择timer4,该如何写这句代码? 首先看tcfg0中选择预分频器1,在看tcfg1里 ...

  4. HDU 5651 xiaoxin juju needs help (组合数)

    xiaoxin juju needs helpTime Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64uSu ...

  5. servlet、genericservlet、httpservlet之间的区别(转)

    当编写一个servlet时,必须直接或间接实现servlet接口,最可能实现的方法就是扩展javax.servlet.genericservlet或javax.servlet.http.httpser ...

  6. 小课堂Week8 例外处理设计的逆袭Part1

    小课堂Week8 例外处理设计的逆袭Part1 今天和大家讲一本书,书名是<例外处理设计的逆袭>. 为什么想讲这本书,是因为,例外处理在程序代码中到处存在,但是这些到底该如何写好,总觉得有 ...

  7. QLineEdit 自动完成(使用setCompleter,内含一个ListView)

    -------------------------------------CompleteLineEdit.h------------------------------------- #ifndef ...

  8. Java并发系列&lbrack;4&rsqb;----AbstractQueuedSynchronizer源码分析之条件队列

    通过前面三篇的分析,我们深入了解了AbstractQueuedSynchronizer的内部结构和一些设计理念,知道了AbstractQueuedSynchronizer内部维护了一个同步状态和两个排 ...

  9. java 集合框架&lpar;十六&rpar;Map

    一.概述 Map是一个包含键值对的集合,一个map不能有重复的键(key),而且每个键至多只能对应一个值.Map同Collection一样,它的所有通用实现都会提供一个转换器构造函数,接收一个Map类 ...

  10. Struts&lpar;十八&rpar;:通过CURD来学习PrepareInterceptor拦截器

    PrepareInterceptor拦截器的用法: 1.若Action实现了Preparable接口,则Action方法需实现prepare()方法: 2.PrepareInterceptor拦截器S ...