【JAVA设计模式】外观模式(Facade Pattern)

一  定义

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


二  案例

一个子系统中拥有3个模块。每一个模块中都有3个方法。当中一个为client调用方法,其它两个则为各子模块间互相调用方法。此时有例如以下需求,client为完毕功能。须要组合3个模块中的方法才干实现功能。

三  未使用模式情况

/*** @Description A模块* @author jerry * @date 2016年4月11日下午2:16:04*/
public interface AModuleApi {public void a1();	//此方法主要用于外部调用public void a2();	//下面双方法主要用于子系统内部间调用public void a3();
}
/*** @Description A模块实现* @author jerry * @date 2016年4月11日下午2:17:10*/
public class AModuleImpl implements AModuleApi {@Overridepublic void a1() {System.out.println("调用了A模块");}@Overridepublic void a2() {//TODO 主要用于子模块间互相调用}@Overridepublic void a3() {//TODO 主要用于子模块间互相调用}
}
/*** @Description B模块* @author jerry * @date 2016年4月11日下午2:16:12*/
public interface BModuleApi {public void b1();	//此方法主要用于外部调用public void b2();	//下面双方法主要用于子系统内部间调用public void b3();
}
/*** @Description B模块实现* @author jerry * @date 2016年4月11日下午2:17:10*/
public class BModuleImpl implements BModuleApi {@Overridepublic void b1() {System.out.println("调用了B模块");}@Overridepublic void b2() {//TODO 主要用于子模块间互相调用}@Overridepublic void b3() {//TODO 主要用于子模块间互相调用}
}
同理。C模块也是如此,篇幅原因。这里不贴代码了,须要代码能够从我github下clone,文末会给出地址。
client调用例如以下:
public class Client {public static void main(String[] args) {AModuleApi a = new AModuleImpl();a.a1();BModuleApi b = new BModuleImpl();b.b1();CModuleApi c = new CModuleImpl();c.c1();}
}
相信非常easy能够写出这种代码。

细致想想能够发现,假设这样写。会存在例如以下问题:

  1. 代码耦合度太高,client与子系统中各模块都有关联。一旦子系统有什么更改,会涉及到client的改动。
  2. 对client学习成本太高。client须要学习各个模块中每一个public方法。知道其什么含义后才干进行调用。


四  使用模式的情况

我们能够在系统这端(即外观模式属于系统这端,若属于客户这端。仍然须要客户去了解每一个模块每一个方法意义,这样无不论什么意义。) 加入一个外观类,由外观类重组须要调用的方法,例如以下所看到的:
/*** @Description 外观类,通常设计成单例* @author jerry * @date 2016年4月11日下午2:43:26*/
public class Facade {private Facade(){}public static void test(){AModuleApi a = new AModuleImpl();a.a1();BModuleApi b = new BModuleImpl();b.b1();CModuleApi c = new CModuleImpl();c.c1();}
}
public class Client {public static void main(String[] args) {
//		AModuleApi a = new AModuleImpl();
//		a.a1();
//		BModuleApi b = new BModuleImpl();
//		b.b1();
//		CModuleApi c = new CModuleImpl();
//		c.c1();Facade.test();}
}
这样一来。client仅仅要与外观类打交道就可以,从而更好地实现了client和子系统各模块的耦合性。

使用外观的目的: 不是给子系统加入新的功能接口,而是让外部降低对子系统内部多个模块的直接交互。松散耦合,从而可以让外部更简单地使用子系统。

当然有时你会有这种需求,client可能仅仅须要调用两个模块就可以,那么现有的外观模式就无法使用了,仅仅好绕开外观类。直接找各模块进行调用。此外,你是否发现。我的ABC模块里面除了有供外部调用的方法外。还有各模块间互相调用的方法,这些方法本不须要client了解。暴露了过多内部细节。会让client产生疑惑,这就是“接口污染  。要解决问题,我们能够将Facade类定义为接口,并对事实上现,使用工厂模式对其创建实例,例如以下所看到的:
public interface FacadeApi {public void a1();public void b1();public void c1();/*** @Description 原有方法,将各模块方法组合调用* @return void* @throws */public void test();
}
/*** @Description 外观接口实现* @author jerry * @date 2016年4月11日下午3:19:25*/
public class FacadeImpl implements FacadeApi {@Overridepublic void a1() {new AModuleImpl().a1();}@Overridepublic void b1() {new BModuleImpl().b1();}@Overridepublic void c1() {new CModuleImpl().c1();}@Overridepublic void test() {a1();b1();c1();}
}
/*** @Description 外观接口实现* @author jerry * @date 2016年4月11日下午3:19:25*/
public class FacadeImpl implements FacadeApi {@Overridepublic void a1() {new AModuleImpl().a1();}@Overridepublic void b1() {new BModuleImpl().b1();}@Overridepublic void c1() {new CModuleImpl().c1();}@Overridepublic void test() {a1();b1();c1();}
}
public class Client {public static void main(String[] args) {
//		AModuleApi a = new AModuleImpl();
//		a.a1();
//		BModuleApi b = new BModuleImpl();
//		b.b1();
//		CModuleApi c = new CModuleImpl();
//		c.c1();//		Facade.test();FacadeApi api = Factory.createFacade();api.test();}
}
这样以后,就对client降低了模块内部方法的暴露。

五  总结

外观模式的本质:封装交互。简化调用
何时使用外观模式:
  1. 假设你希望为一个复杂的子系统提供一个简单接口
  2. 假设构建多层结构的系统。能够考虑使用外观模式,使用外观对象作为每层的入口,这样能够简化层间调用,能够减少耦合度。
------------------------------------------------------------------------------------------------------------------------------------------
Github:  https://github.com/jerry-sc/designPattern
Reference:《研磨设计模式》

转载于:https://www.cnblogs.com/yangykaifa/p/7290448.html

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

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

相关文章

return的用处

#include "stdio.h" main() {int a,b1,c0;for(a1;a<5;a){ cca;}printf("%d",c);return ;printf("hello word"); } 输出结果是10并没有hello word&#xff1b;return将不会执行下面的语句。转载于:https://www.cnblogs.com/doublekai/p/6148…

静态时序分析——Clock Gating check

门控时钟是RTL级进行低功耗设计的最常用方法&#xff0c;能够有效降低动态功耗。在实际使用中&#xff0c;一般用ICG&#xff08;集成门控时钟单元&#xff09;来完成clock gating。ICG电路和时序如下&#xff1a; 通常来说&#xff0c;工艺库已经集成了ICG&#xff0c;在做门控…

U-boot中TFTP 解释

http://www.cnblogs.com/heaad/archive/2009/08/10/1542538.html

BlackHat Arsenal USA 2018 ToolsWatch黑客工具库

原文链接&#xff1a;https://medium.com/hack-with-github/black-hat-arsenal-usa-2018-the-w0w-lineup-7de9b6d32796 Black Hat Arsenal USA 2018 — The w0w lineup After the huge success of Black Hat Arsenal USA 2017, toolswatch has now announced the list of too…

SOA是什么

SOA是什么&#xff1f; SOA是面向服务的架构&#xff0c;是一个组件模型&#xff0c;它将应用程序的不同功能单元&#xff08;称为服务&#xff09;通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的&#xff0c;它独立于实现服务的硬件平台、操作…

redis 优化

系统优化echo "vm.overcommit_memory1" > /etc/sysctl.conf 0&#xff0c; 表示内核将检查是否有足够的可用内存供应用进程使用&#xff1b;如果有足够的可用内存&#xff0c;内存申请允许&#xff1b;否则&#xff0c;内存申请失败&#xff0c;并把错误返回给应…

IC设计常见设计思想

速度与面积互换原则 所谓速度&#xff0c;是指整个工程稳定运行所能够达到的最高时钟频率&#xff0c;它不仅和电路内部各个寄存器的建立时间、保持时间以及外部器件接口的各种时序要求有关&#xff0c;而且还和两个紧邻的寄存器间的逻辑延时&#xff0c;走线延时有关。所谓面…

DM365 u-boot启动分析

http://www.61ic.com/Article/DaVinci/DM644X/201009/27429.html

(十三)Hibernate高级配置

配置数据库连接池 配置C3P0连接池。先导入c3p0包。然后在hibernate.cfg.xml文件中 &#xff0c;使用下面代码配置连接池<property name"hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>可以通过下面的…

eclipse中如何配置tomcat

1.打开eclipse上面的Windows选项&#xff0c;选择Preferences>Server>Runtime Environments>Add 2.选择你电脑中安装的tomcat的版本我的是8所以我选的是Apache Tomcat v8.0 3,Next>Browse选择Tomcat的安装目录&#xff0c;选择jdk 4.Finish>OK tomcat配置完成。…

jsp调试小技巧

console.log($("#toolbar")); 打印对象可知道这个对象的参数信息转载于:https://www.cnblogs.com/chenweida/p/6149342.html

数字IC验证学习(一)

一、数据类型 1、logic logic类型只能有一个驱动。使用wire和reg的地方均可使用logic&#xff0c;但如双向总线等有多个驱动的地方&#xff0c;则不可使用logic。 2、二值逻辑 对于二值逻辑变量与DUT中的四值逻辑变量连接时&#xff0c;如果DUT中产生了X和Z&#xff0c;会被…

SecureCRT 配置文件中 找密码

打开本地电脑如下路径 C:\Users\XXX\AppData\Roaming\VanDyke\Config\Sessions 找到配置文件。 运行命令&#xff1a;python SecureCRTDecrypt.py [配置文件名称] 例如&#xff1a;python SecureCRTDecrypt.py 192.168.1.249.ini ssh root192.168.1.249 # 123456 即可得到密…

刷题比赛

题目描述 给你四个数组A,B,C,D. 给出每个数组的初始值A[1] 1, B[1] 1, C[1] 1, D[1] 1 , A[2] 3, B[2] 3, C[2] 3, D[2] 3; 有以下的递推公式: (1) a[k2]p* a[k1]qa[k]b[k1]c[k1]r k^2t * k1d[k]; (2)b[k2]u* b[k1]vb[k]a[k1]c[k1]w^kd[k]; (3)c[k2]x c[k1]yc[k]a[k1]b[…

自动化测试用例设计原则

自动化测试用例设计原则&#xff1a;每一个用例 都是一个闭合的业务操作。用例之间要保持独立 &#xff0c;不要有操作上的依赖关系&#xff0c;就算有也是测试数据上的依赖。第二个用例 依赖第一个用例产生的数据。转载于:https://www.cnblogs.com/yyjiangnan/p/6149430.html

MII/MDIO接口详解

MII/MDIO接口详解 http://dpinglee.blog.163.com/blog/static/144097753201041131115262/

T24412 Cup#182-3 洞穴之旅

弱连通模板题&#xff0c;不过还是不会。。。 这道题在POJ2762有&#xff0c;这个出题人直接翻译弄过来了。。。 弱连通的定义是&#xff1a;从u能到达v或从v能到达u&#xff0c;则u和v这两个点弱连通。 显然如果是强连通分量就一定是弱连通分量啦&#xff0c;所以可以直接缩点…

PCB相关的基础知识

http://www.elecfans.com/article/89/92/2017/20170425510728.html转载于:https://www.cnblogs.com/jackn-crazy/p/7300228.html