当前位置: 首页 > 科技观察

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

时间:2023-03-18 18:52:04 科技观察

大家好,我是老天。从今天开始,我每周都会给你福利。我会给你什么?应该是技术书。不要做那么多花里胡哨的事情。参与方式见文末。好了,进入正题,今天给大家分享一下设计模式中的门面模式。用恰当的生活故事和真实的项目场景来描述设计模式,最后用一句话概括这个设计模式。故事开发的朋友都知道后端开发一般是:controller---servie---dao/mapper/repository。但是,我问了很多人,他们熟悉门面模式吗?有的工作了五年还不知道。今天,老田就带大家来看看门面模型。FacadePattern概述FacadePattern也称为外观模式,为访问子系统中的一组接口提供了一个统一的接口。它的主要特点是定义了一个高层接口,使子系统更易于使用,属于结构化设计模式。Chinese:为子系统中的一组接口提供统一的接口。Facade定义了一个更高级的接口,使子系统更易于使用。其实在我们日常的编码工作中,我们都有意无意地使用Facade模式。每当高层模块需要调度多个子系统(超过2个类对象)时,我们都会有意识地创建一个新的类来封装这些子系统,并提供简化的接口,让高层模块更方便的调用函数这些子系统间接。生活中的案例关于门面模式,生活中有很多案例。案例一:你去银行办理业务,有前台接待你。然后,前台会问你需要办理什么业务,他会一一带你办理,这样我们就不用瞎折腾到处找对应的业务窗口了。这种前台人员相当于门面模式。案例二:我们盖房子,如果没有承包商,那你就得自己找水泥工、电工、装修工等。但是如果你有一个承包商,你就不必做这些工作,直接告诉承包商你需要一个电工来修理线路。这个contractor可以理解为一个门面模型。Case3:我们后端开发的controller也可以理解为门面模式。比如获取用户账号信息,先查看UserService获取用户信息,再查看UserAccountService用户账号信息。Facade模式适用场景在软件系统中,Facade模式适用于以下应用场景。为外部访问复杂模块或子系统提供简洁的接口。当你想增加子系统的独立性时。当子系统由于无法避免的临时原因可能出现bug或性能相关问题时,可以通过门面模式提供高层接口,隔离客户端与子系统的直接交互,防止代码污染。门面模式的一般写法是用代码实现一个简单的门面模式,因为我们最喜??欢的是从demo入手。业务场景:现在需要调用三个服务各自的方法:);}}publicclassServiceC{publicvoiddoC(){System.out.println("doServiceC");}}当不引入门面模式时,client这样调用:publicclassClient{publicstaticvoidmain(String[]args){ServiceAserviceA=newServiceA();ServiceBserviceB=newServiceB();ServiceCserviceC=newServiceC();serviceA.doA();serviceB.doB();serviceC.doC();}}每次客户端都需要创建很多服务对象,如果涉及到有很多服务,这段代码是不是很别扭?会有很多重复的代码。运行结果doServiceAdoServiceBdoServiceC现在我们来添加门面模式:publicclassFacade{//是不是很像在我们的controller中注入各种服务?privateServiceAserviceA=newServiceA();privateServiceBserviceB=newServiceB();privateServiceCserviceC=newServiceC();publicvoiddoA(){serviceA.doA();}publicvoiddoB(){serviceB.doB();}publicvoiddoC(){serviceC.doC();}}客户端变为:publicclassClient{publicstaticvoidmain(String[]args){//简单易行大功告成,创建门面对象即可。Facadefacade=newFacade();facade.doA();facade.doB();facade.doC();}}运行结果:doServiceAdoServiceBdoServiceC门面模式UML图结合本UML图,经过银行前台人员案例回顾和承包商,更容易理解门面模型。门面模式中的角色从上图可以看出,门面模式主要包括2个角色。门面角色(Facade):也叫门面角色,是系统对外的统一接口。子系统角色(Service):可以同时存在一个或多个Service。每个服务不是一个单独的类,而是类的集合。服务不知道Facade的存在。对于Services,Facade只是另一个客户端(即Facade对ServiceA、ServiceB和ServiceC是透明的)。门面模式的扩展优势●减少系统相互依赖  想一想,如果我们不使用门面模式,外部访问直接深入到子系统,彼此之间有很强的耦合关系。你活着,我也活着。如此强的依赖性在系统设计中是不可接受的。门面模式的出现很好的解决了这个问题。所有的依赖都依赖于门面对象,与子系统无关。●增加灵活性  依赖减少,灵活性自然提高。不管子系统如何变化,只要不影响门面对象,就可以自由移动。●提高安全性  允许您访问子系统的业务,该子系统的逻辑被启用。如果您不在外观上启用该方法,您将永远无法访问它。缺点在增加子系统和扩展子系统的行为时,很容易带来未知的风险。不符合开闭原则。在某些情况下,可能会违反单一职责原则。大神们怎么用呢?Spring中也有很多门面模式,比如org.springframework.jdbc.support.JdbcUtils我们来看看方法Connectioncon=null;try{con=DataSourceUtils.getConnection(dataSource);DatabaseMetaDatametaData=con.getMetaData();if(metaData==null){//.....}returnaction.processMetaData(metaData);}}...方法都给我封装好了。对于我们的开发人员,我只需要将JdbcUtils类作为目标。我不必担心Connection、ResultSet等是如何创建的。当我调用JdbcUtils对应的方法时,就可以拿到对应的对象了。Mybatis中也使用门面模式,如:org.apache.ibatis.session.Configuration在Configuration中以new开头,如:publicExecutornewExecutor(Transactiontransaction){returnnewExecutor(transaction,defaultExecutorType);}publicMetaObjectnewMetaObject(Objectobject){returnMetaObject。forObject(object,objectFactory,objectWrapperFactory,reflectorFactory);}publicParameterHandlernewParameterHandler(MappedStatementmappedStatement,ObjectparameterObject,BoundSqlboundSql){...returnparameterHandler;}publicResultSetHandlernewResultSetHandler(Executorexecutor,MappedStatementmappedStatement,RowBoundsrowBounds,ParameterHandlerparameterHandler,ResultHandlerresultHandler,BoundSqlboundSql){...returnresultSetHandler;}publicStatementHandlernewStatementHandler(ExecutorExecutor,MappedStatementmappedStatement){...}对于调用这些方法的地方,他不知道怎么创建新的对象,直接用就可以了。Tomcat中还有一种门面模式,例如:org.apache.catalina.connector.RequestFacade,从名字就知道它使用的是门面模式。它封装了很多请求操作,也集成了很多servlet-api以外的内容,为用户提供了极大的方便。同样,Tomcat也为Response和Session封装了相应的ResponseFacade类和StandardSessionFacade类。有兴趣的小伙伴可以详细了解一下。PS:基本上所有以Facade结尾的类都使用facade模式。参考:Tom的设计模式课程总结过。我已经分享了很多关于外观模式的内容。看完这篇文章,是不是觉得门面模式其实很简单?另外,你也可以考虑一下能不能在工作中使用。同时,面试有时也可以用来吹牛。最后,我可以用一句话总结门面模型:打开一扇门,走向全世界。本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。