您好,欢迎访问一九零五行业门户网

工作五年了,居然还不懂 门面模式!

好啦,进入我们的主题,今天我给大家分享设计模式中的门面模式。用贴切的生活故事,以及真实项目场景来讲设计模式,最后用一句话来总结这个设计模式。
故事 开发的朋友都知道,后端开发通常都是:
controller---servie---dao/mapper/repository
但是,我问过很多人,熟悉门面模式不?有的工作五年了都不知道。
今天老田,就带你来看看门面模式。
门面模式概述 门面模式(facade pattern)又叫作外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型设计模式。
英文:
provide a unified interface to a set of interfaces in asubsystem.facade defines a higher-level interface that makes thesubsystem easier to use.
其实,在日常编码工作中,我们都在有意无意地大量使用门面模式。但凡只要高层模块需要调度多个子系统(2个以上类对象),我们都会自觉地创建一个新类封装这些子系统,提供精简的接口,让高层模块可以更加容易地间接调用这些子系统的功能。
生活中的案例 关于门面模式,在生活中的案例,非常之多。
案例1:去银行办理业务,有个前台接待你,然后,这个前台会问你需要办什么业务,他会一个一个带你办理,这样我们就不需要到处乱串、到处找对应业务窗口了。这个前台人员就相当于门面模式。
案例2:我们建房子,如果没有包工头的话,那就是你自己要去找水泥工,电工、装修工等。但如果有了包工头,这些活你都不用干了,直接跟包工头说,需要电工来把线路搞好。这个包工头就可以理解为门面模式。
案例3:我们后端开发的controller,也可以理解为门面模式,比如说获取用户账户信息,先查userservice获取用户信息,然后查useraccountservice用户账户信息。
门面模式适用场景 在软件系统中,门面模式适用于以下应用场景。
为一个复杂的模块或子系统提供一个简洁的供外界访问的接口。希望提高子系统的独立性时。当子系统由于不可避免的暂时原因导致可能存在bug或性能相关问题时,可以通过门面模式提供一个高层接口,隔离客户端与子系统的直接交互,预防代码污染。门面模式通用写法 还是使用代码来实现一个简单的门面模式,因为咱们最喜欢的就是从demo开始。
业务场景:现在需要调用三个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(); }}
每次,客户端自己都需要创建很多service对象,如果涉及到有很多个service,那这代码不是很尴尬吗?会出现大量重复性的代码。
运行结果
do serviceado servicebdo servicec

下面我们就来加入门面模式:
public class facade { //是不是很像我们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) { //轻轻松松的搞定,只需要创建门面这个对象即可 facade facade=new facade(); facade.doa(); facade.dob(); facade.doc(); }}
运行结果:
do serviceado servicebdo servicec

门面模式uml图
结合这个uml图,在回顾银行前台人员和包工头的案例,就更轻松的理解门面模式了。
门面模式中的角色由上图可以看到,门面模式主要包含2个角色。
外观角色(facade):也叫作门面角色,是系统对外的统一接口。子系统角色(service):可以同时有一个或多个service。每个service都不是一个单独的类,而是一个类的集合。service们并不知道facade的存在,对于service们而言,facade 只是另一个客户端而已(即facade对servicea、serviceb、servicec透明)。门面模式的扩展优点● 减少系统的相互依赖想想看,如果我们不使用门面模式,外界访问直接深入到子系统内部,相互之间是一种强耦合关系,你死我就死,你活我才能活,这样的强依赖是系统设计所不能接受的,门面模式的出现就很好地解决了该问题,所有的依赖都是对门面对象的依赖,与子系统无关。
● 提高了灵活性依赖减少了,灵活性自然提高了。不管子系统内部如何变化,只要不影响到门面对象,任你自由活动。
● 提高安全性想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到 。
缺点当增加子系统和扩展子系统行为时,可能容易带来未知风险。不符合开闭原则。某些情况下,可能违背单一职责原则。大神们是如何使用的 在spring中也是有大量使用到门面模式,比如说
org.springframework.jdbc.support.jdbcutils
再来看看其中的方法
public static void closeconnection(@nullable connection con) { con.close();}public static object extractdatabasemetadata(datasource datasource, databasemetadatacallback action) throws metadataaccessexception { connection con = null; try { con = datasourceutils.getconnection(datasource); databasemetadata metadata = con.getmetadata(); if (metadata == null) { //..... } return action.processmetadata(metadata); }}......
都是给我封装好了方法,对于我们开发者来说,我只面向jdbcutils这一个类就好了,我不用去管connection、resultset等是怎么创建的,需要的时候,我调用jdbcutils的对应方法即可获得对应的对象。
在mybatis中也是用到了门面模式,比如:
org.apache.ibatis.session.configuration
在configuration中以new开头的方法,比如:
public executor newexecutor(transaction transaction) { return newexecutor(transaction, defaultexecutortype);}public metaobject newmetaobject(object object) { return metaobject.forobject(object, objectfactory, objectwrapperfactory, reflectorfactory);}public parameterhandler newparameterhandler(mappedstatement mappedstatement, object parameterobject, boundsql boundsql) { ... return parameterhandler;}public resultsethandler newresultsethandler(executor executor, mappedstatement mappedstatement, rowbounds rowbounds, parameterhandler parameterhandler, resulthandler resulthandler, boundsql boundsql) { ... return resultsethandler;}public statementhandler newstatementhandler(executor executor, mappedstatement mappedstatement){ ...}
对于调用这些方法的地方,他并不知道是怎么new出来的对象,只管使用就行了。
在tomcat中也有门面模式,比如:
org.apache.catalina.connector.requestfacade
从名字就知道它用了门面模式。它封装了非常多的request操作,也整合了很多servlet-api以外的内容,给用户使用提供了很大便捷。同样,tomcat针对response和session也封装了对应的responsefacade类和standardsessionfacade类,感兴趣的小伙伴可以深入了解一下。
ps:基本上所有以facade结尾的类,都是使用到了门面模式。
参考:tom的设计模式课程
总结 好了,关于门面模式就分享这么多,看完本文是不是觉得门面模式其实很简单的,另外在工作也可以考虑是不是可以把它用上,同时,面试的时候也可以用来吹吹。
以上就是工作五年了,居然还不懂 门面模式!的详细内容。
其它类似信息

推荐信息