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

设计模式系列—外观模式

时间:2023-03-19 15:31:40 科技观察

前言23设计模式速记单例模式工厂方法模式抽象工厂模式Builder/Builder模式原型模式分享元素(享元)模式持续更新中...23种设计模式快速记忆,拜托阅读上面的第一篇文章。本文就和大家一起了解外观(facade)模式。外观模式一定是我们平时使用最多的一种。总体概览模式定义为子系统中的一组接口提供了一个一致的接口,Facade模式定义了一个高层接口,使子系统更易于使用。通过创建一个统一的门面类来包装子系统中的一个/多个复杂类,客户端可以通过调用门面类的方法来调用内部子系统中的所有方法。解决的问题避免了系统间的高度耦合,使得复杂子系统的使用变得简单。实例说明第一步:定义子系统角色}}classSubSystemThree{publicvoidmethodThree(){System.out.println("子系统方法三");}}classSubSystemFour{publicvoidmethodFour(){System.out.println("子系统方法四");}}第二步:定义门面角色类Facade{SubSystemOneone;SubSystemTwotwo;SubSystemThreethree;SubSystemFourfour;publicFacade(){this.one=newSubSystemOne();this.two=newSubSystemTwo();this.three=newSubSystemThree();this.four=newSubSystemFour();}publicvoidMethodA(){System.out.println("方法组A()----");one.methodOne();two.methodTwo();four.methodFour();}publicvoidMethodB(){System.out.println("MethodGroupB()----");two.methodTwo();three.methodThree();}}第三步:验证输出结果/***appearance/facadepattern*/publicclassFacadePattern{publicstaticvoidmain(String[]args){Facadefacade=newFacade();facade.MethodA();facade.MethodB();System.out.println("----over----");}}输出结果如下:方法组A()---子系统方法一子系统方法二子系统方法四方法组B()----子系统方法2子系统方法3----over---优点减少系统的相互依赖;外观模式通过对子系统的封装,为上层模块提供统一的接口,从而减少上层模块与子系统的Over-coupling;提高灵活性;提高了安全性缺点不符合开闭原则:当外观类没有抽象出来的时候,如果需要增加新的子系统,需要修改Facade类。应用场景需要为复杂的子系统提供简单的接口,以提供子系统的独立性。客户端程序与多个子系统之间存在较大的依赖关系。引入外观类,将子系统与客户端和其他子系统解耦。提高了子系统的独立性和可移植性。在层级结构中,可以使用外观模式来定义系统中每一层的入口层级??。层与层之间没有直接联系,而是通过外观类建立联系,降低层与层之间的耦合度。外观模式和适配器模式的区别在于,外观模式的实现核心主要是:外观类用于保存各个子系统的引用,用一个统一的外观类来封装多个子系统类。而客户端只需要引用这个外观类,然后Facade类就可以调用各个子系统中的方法了。这种实现方式与适配器模式非常相似,但外观模式与适配器模式的区别在于,适配器模式包装了一个对象以改变其接口,而外观则“包装”了一组对象以简化其接口。它们的用意不同,适配器是将接口转换成不同的接口,而外观模式是提供统一的接口来简化接口。源码中的应用#tomcatorg.apache.catalina.connector.RequestFacadeorg.apache.catalina.connector.ResponseFacade#mybatisConfiguration......RequestFacade源码分析Tomcat使用了很多facade模式,因为里面有很多不同的组件Tomcat,每个组件都需要相互通信,但是又不能把自己内部的数据暴露给其他组件太多。使用外观模式隔离数据是一种很好的方法。Tomcat中的Request除了实现ServletRequest接口外,还有一些额外的函数,这些函数需要被其他类调用,但是这些方法不应该暴露给上层,因为上层应该专注于实现服务小程序请求。所以在Tomcat中会采用Facade模式。使用Facade模式之前,如下:使用Facade模式之前的流程处理请求.service((ServletRequest)request,(ServletResponse)response);}}使用Facade模式后如下:使用Facade后的流程处理请求是这样的publicclassServletProcess{publicvoidprocess(Requestrequest,Responseresponse){//....RequestFacaderequestFacade=newRequestFacade(request);ResponseFacaderesponseFacade=newResponseFacade(response);servlet=(Servlet)myClass.newInstance();servlet.service((ServletRequest)requestFacade,(ServletResponse)responseFacade);}}为了实现这个效果,RequestFacade使用了类似代理模式的方法来实现。publicclassRequestFacadeimplementsHttpServletRequest{privateServletRequestrequest;publicRequestFacade(ServletRequestrequest){this.request=request;}@OverridepublicStringgetAuthType(){returnrequest.getAuthType();}}对象中有一个ServletRequest对象,RequestFacade的所有调用方法都会委托给SquestFacade配置源码分析从上面的类图可以看出,客户端只需要调用Configuration的newMetaObject(Objectobject)方法就可以得到一个MetaObject对象,具体对象如何生成与客户端无关。下面看一下Configuration部分的源码分析。Configuration部分代码//配置类:publicclassConfiguration{protectedReflectorFactoryreflectorFactory=newDefaultReflectorFactory();protectedObjectFactoryobjectFactory=newDefaultObjectFactory();protectedObjectWrapperFactoryobjectWrapperFactory=newDefaultObjectWrapperFactory();publicMetaObjectnewMetaObject(Objectobject){returnoryMetaObject.forObject,object,objectWrapperFactory};MetaObject类publicclassMetaObject{privateObjectoriginalObject;privateObjectWrapperobjectWrapper;privateObjectFactoryobjectFactory;privateObjectWrapperFactoryobjectWrapperFactory;privateReflectorFactoryreflectorFactory;publicstaticMetaObjectforObject(Objectobject,ObjectFactoryobjectFactory,ObjectWrapperFactoryobjectWrapperFactory,ReflectorFactoryreflectorFactory){if(object==null){returnSystemMetaObject.NULL_META_OBJECT;}else{returnnewMetaObject(object,objectFactory,objectWrapperFactory,reflectorFactory);}}privateMetaObject(Objectobject,ObjectFactoryobjectFactory,ObjectWrapperFactoryobjectWrapperFactory,ReflectorFactoryreflectorFactory){this.originalObject=object;this.objectFactory=objectFactory;this.objectWrapperFactory=objectWrapperFactory;this.reflectorFactory=reflectorFactory;如果(objectinstanceofObjectWrapper){this.objectWrapper=(ObjectWrapper)object;}elperseif(object.WraphasWrapperFor(object)){this.objectWrapper=objectWrapperFactory.getWrapperFor(this,object);}elseif(objectinstanceofMap){this.objectWrapper=newMapWrapper(this,(Map)object);}elseif(objectinstanceofCollection){this.objectWrapper=newCollectionWrapper(this,(Collection)object);}else{this.objectWrapper=newBeanWrapper(this,object);}}}从上面部分源码可以看出,客户端只需要调用newMetaObject(Objectobject)方法,通过传递一个Object参数,可以得到对应的MetaObject。至于具体生成什么样的MetaObject,有MetaObject类的forObject(object,objectFactory,objectWrapperFactory,reflectorFactory)方法来实现PS:以上代码提交到Github:https://github.com/Niuh-研究/niuh-designpatterns.git