试百客 专业做试用的网站,电商网站运营方案,精准流量推广,企业标识设计经典案例1、适配器模式的理解
适配器模式可以理解为有两个现成的类Adaptee和Target#xff0c;它们两个是不能动的#xff0c;要求必须使用B这个类来实现一个功能#xff0c;但是A的内容是能复用的#xff0c;这个时候我们需要编写一个转换器
适配器模式
Adaptee#xff1a;被适…1、适配器模式的理解
适配器模式可以理解为有两个现成的类Adaptee和Target它们两个是不能动的要求必须使用B这个类来实现一个功能但是A的内容是能复用的这个时候我们需要编写一个转换器
适配器模式
Adaptee被适配者现有的接口或者类Adapter适配器类适配器模式的核心转换作用Target目标接口或者类
适配器模式的实现步骤
定义目标接口即客户端所期望的接口。定义适配器类继承目标接口并包含一个适配者对象。在适配器类中实现目标接口的方法调用适配者对象的相关方法进行适配。在客户端中使用适配器类进行操作。
适用场景
继承需要用到别人的类但是不能修改多适配者多个不同的对象需要让他们具有相同的方法缺省形式
适配器模式有类适配器和对象适配器两种方式一般采用前者
2、继承场景
来公司第二天写一个简单的业务看到同事写的接口中5个方法有3个正好可以用的但是还需要另外新增一个于是我便开始了改造(新增一个方法)提交后同事大发雷霆谁让你新增的新增了这个方法这个接口就失去了本来的意思。。。。。。
我去***那算了我还是自己写一个吧想想怎么能在不懂他的接口前提下复用一下他的代码那边使用适配器模式
//同事的接口为被适配者
public interface Adaptee{void method1();void method2();void method3();void method4();void method5();
}
public class AdapteeImpl implements Adaptee {Overridepublic void method1() {System.out.println(method1 execute......);}Overridepublic void method2() {System.out.println(method2 execute......);}Overridepublic void method3() {System.out.println(method3 execute......);}Overridepublic void method4() {System.out.println(method4 execute......);}Overridepublic void method5() {System.out.println(method5 execute......);}
}//我需要使用的接口为目标接口
public interface Target{void method1();void method2();void method3();void method6();
}//构建适配器类Adapter
//方式一类适配器方式
public class Adapter1 extends AdapteeImpl implements Target {Overridepublic void method6() {System.out.println(method6 execute......);}
}public class Client {public static void main(String[] args) {Target target new Adapter1();target.method1();target.method2();target.method3();target.method6();}
}//方式二对象适配器方式
public class Adapter2 implements Target {private Adaptee adaptee;public Adapter2(Adaptee adaptee) {this.adaptee adaptee;}Overridepublic void method1() {adaptee.method1();}Overridepublic void method2() {adaptee.method2();}Overridepublic void method3() {adaptee.method3();}Overridepublic void method6() {System.out.println(method6 execute......);}
}public class Client {public static void main(String[] args) {Target target new Adapter2(new AdapteeImpl());target.method1();target.method2();target.method3();target.method6();}
}3、多适配者
多个适配者适配同一个目标接口为每一个适配者创建一个适配器
这种是最常用的方式在springMVC和AOP中都有用到后面会进行解析
例新能源汽车的发动机有电能发动机Electric Motor和光能发动机Optical Motor等各种发动机的驱动方法不同例如电能发动机的驱动方法 electricDrive() 是用电能驱动而光能发动机的驱动方法 opticalDrive() 是用光能驱动它们是适配器模式中被访问的适配者。
客户端希望用统一的发动机驱动方法 drive() 访问这两种发动机所以必须定义一个统一的目标接口 Motor然后再定义电能适配器Electric Adapter和光能适配器Optical Adapter去适配这两种发动机。 package adapter;//目标发动机
interface Motor {public void drive();
}//适配者1电能发动机
class ElectricMotor {public void electricDrive() {System.out.println(电能发动机驱动汽车);}
}//适配者2光能发动机
class OpticalMotor {public void opticalDrive() {System.out.println(光能发动机驱动汽车);}
}//电能适配器
class ElectricAdapter implements Motor {private ElectricMotor emotor;public ElectricAdapter() {emotornew ElectricMotor();}public void drive() {emotor.electricDrive();}
}//光能适配器
class OpticalAdapter implements Motor {private OpticalMotor omotor;public OpticalAdapter() {omotornew OpticalMotor();}public void drive() {omotor.opticalDrive();}
}//客户端代码
public class MotorAdapterTest {public static void main(String[] args) {System.out.println(适配器模式测试);Motor motor(Motor)ReadXML.getObject();motor.drive();}
}4、缺省形式
缺省就是对于一个具有很多方法的接口我没只需要其中几个不想把所有的方法都实现一遍可以写一个抽象类作为适配器再去继承该适配器
public interface Adaptee {void model1();void model2();void model3();void model4();void model5();void model6();void model7();void model8();void model9();void model10();
}public abstract class Adapter implements Adaptee{Overridepublic void model1() {}Overridepublic void model2() {}Overridepublic void model3() {}Overridepublic void model4() {}Overridepublic void model5() {}Overridepublic void model6() {}Overridepublic void model7() {}Overridepublic void model8() {}Overridepublic void model9() {}Overridepublic void model10() {}
}public class Target extends Adapter{Overridepublic void model3() {System.out.println(model3......);}Overridepublic void model7() {System.out.println(model7......);}
}5、spring中的适配器模式
5.1 SpringMVC
请求处理流程
HandlerAdapter 在 Spring MVC 中使用了适配器模式。HandlerAdapter 主要用于支持不同类型的处理器如 Controller、HttpRequestHandler 或者 Servlet 等让它们能够适配统一的请求处理流程。这样Spring MVC 可以通过一个统一的接口来处理来自各种处理器的请求。在 Spring MVC 的工作流程中HandlerAdapter 扮演了一个重要角色。以下是其工作原理的简化版 DispatcherServlet前端控制器Front Controller负责接收所有请求并将其分发给相应的处理程序HandlerMapping处理器映射器立请求URL与处理程序之间的映射关系默认为RequestMappingHandlerMapping根据Controller注解和RequestMapping注解来进行URL与处理程序的映射可以在Spring配置文件如XML配置文件或Java配置类中显式地配置所需的HandlerMappingHandlerAdapter处理器适配器通过handlerMapping获取到对应的处理程序handler(controller)后通过所有注册的handlerAdapter的supports()方法找到对应的适配器来调用当存在多个合适的HandlerAdapter时框架会根据一定规则进行判断和选择 用户发起一个 HTTP 请求到 Spring MVC 应用。DispatcherServlet 接收到请求后首先会调用 HandlerMapping寻找合适的处理器Handler来处理这个请求。找到合适的处理器后DispatcherServlet 需要找到一个能够处理这个处理器的 HandlerAdapter。为此它会遍历所有已注册的 HandlerAdapter调用它们的 supports 方法检查它们是否支持当前处理器。找到支持当前处理器的 HandlerAdapter 后DispatcherServlet 会调用该 HandlerAdapter 的 handle 方法将请求委托给处理器进行处理。处理器处理完请求后会返回一个 ModelAndView 对象DispatcherServlet 会将这个对象传递给适当的 ViewResolver以解析视图并将响应返回给用户。 我们在Controller、Service、Mapper中写的业务逻辑在HandlerAdapter的处理过程中执行 以下是一个简化的 HandlerAdapter 接口示例
public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}Spring MVC 提供了一些内置的 HandlerAdapter 实现如RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter 是 Spring MVC 中内置的几个 HandlerAdapter 实现它们分别用于支持不同类型的处理器。
RequestMappingHandlerAdapter支持基于注解的处理器如使用 Controller 和 RequestMapping 注解的处理器方法。这是 Spring MVC 中最常用的处理器类型。SimpleControllerHandlerAdapter支持实现 org.springframework.web.servlet.mvc.Controller 接口的处理器。这是 Spring MVC 早期版本中的处理器类型现在已经较少使用。HttpRequestHandlerAdapter支持实现 org.springframework.web.HttpRequestHandler 接口的处理器。这种类型的处理器主要用于处理静态资源如图片、样式表等。
举例
Controller
RequestMapping(/user)
public class UserController {GetMapping(/{id})public String getUserById(PathVariable(id) Long id, Model model) {// 执行业务逻辑return userDetails;}
}在上述例子中有一个controller当spring接收到请求时处理过程为
假设我们使用了默认的配置和注解驱动。
1、首先前端控制器DispatcherServlet会根据请求的 URL 路径来选择合适的 HandlerMapping。在 Spring MVC 中默认使用的是 RequestMappingHandlerMapping它会根据 RequestMapping 注解以及其他相关注解来确定处理程序handler与请求路径之间的映射关系。
2、 对于 UserController 中的 getUserById() 方法使用了 GetMapping 注解并指定了路径为 “/{id}”。因此当客户端发送 GET 请求到 “/user/{id}” 路径时RequestMappingHandlerMapping 就会匹配到这个处理程序(handler)。
3、 接下来在执行处理程序之前前端控制器还需要选择合适的 HandlerAdapter并将请求委托给它来执行处理程序。
4、对于标注有 GetMapping、PostMapping 等注解的方法默认情况下会选择 RequestMappingHandlerAdapter 作为主要的 HandlerAdapter。
5、RequestMappingHandlerAdapter 是一个功能强大且灵活的适配器能够处理包含模型数据、参数绑定、异常处理等复杂情况。
在上述例子中当通过 RequestMappingHandlerMapping 匹配到 UserController 的 getUserById() 方法后前端控制器就会选择 RequestMappingHandlerAdapter 来执行这个处理程序并传递相应的请求参数和模型数据给该方法。 在 Spring MVC 中前端控制器DispatcherServlet会根据请求路径和方法来选择合适的 HandlerAdapter。 选择后HandlerAdapter 将接收到的请求参数、模型数据等信息传递给相应的处理程序业务逻辑并执行该处理程序。 HandlerAdapter 根据具体的处理程序类型来确定调用哪个方法以及如何将请求数据传递给该方法。 不同类型的处理程序可能有不同的要求和处理方式。 例如在使用注解配置的方法作为处理程序时默认情况下会选择 RequestMappingHandlerAdapter。 RequestMappingHandlerAdapter 会根据注解中定义的规则将请求参数、路径变量、请求体内容等绑定到方法的入参上并调用该方法执行业务逻辑。它还能够通过模型对象Model来向视图传递数据。 可以说 HandlerAdapter 是负责将请求数据传递给我们自己编写的业务逻辑处理程序并执行其中定义的方法。它是框架与业务代码之间进行通信和协调的重要环节。 自定义handlerAdapter 通常情况下Spring MVC 默认提供的 HandlerAdapters 是能够满足大多数应用场景的并且能够处理各种类型的处理程序handler。 在某些特殊情况下可能需要自定义 HandlerAdapter 来满足特定的需求。以下是一些需要自定义 HandlerAdapter 的情况 需要支持新的处理程序类型如果你使用了自定义的处理程序类型而该类型不属于 Spring MVC 默认支持的类型那么你可以编写自己的 HandlerAdapter 来支持该类型。 特定的请求/响应方式如果你想要处理一种不常见或非标准的请求/响应方式例如 WebSocket、SSE服务器发送事件等你可能需要编写一个适配器来处理这些方式。 定制化业务逻辑如果你有特殊的业务需求需要在执行业务逻辑之前或之后添加额外的逻辑操作例如权限校验、日志记录等你可以编写一个自定义 HandlerAdapter 来扩展框架提供的功能。 性能优化如果你对性能有极高要求并希望通过优化执行过程来提升系统性能可以根据具体场景编写一个更高效的 HandlerAdapter 来替换默认实现。 总之在需要与 Spring MVC 框架进行更深度集成、满足特定需求或优化性能时可以考虑自定义 HandlerAdapter。但在大多数情况下默认提供的 HandlerAdapters 能够满足开发需求。 handlerAdapter的适配器模式
可以看到处理器的类型不同有多重实现方式那么调用方式就不是确定的如果需要直接调用 Controller 方法需要调用的时候就得不断地使用 if else 来进行判断是哪一种子类然后执行。那么如果后面要扩展 Controller 就得修改原来的代码这样违背了 OCP 原则 下面手写一下handlerAdapter的选择流程
//controller类我们自己写的逻辑即handler
public interface Controller {}public class AnnotationController implements Controller{public void doAnnotationHandler() {System.out.println(annotation...);}
}public class HttpController implements Controller{public void doHttpHandler() {System.out.println(http...);}
}public class SimpleController implements Controller{public void doSimpleHandler() {System.out.println(simple...);}
}//handlerAdapter类 处理器适配器
//通过handlermapping获取到对应的handler后再查找对应的处理器适配器调用对应方法
public interface HandlerAdapter {boolean supports(Object handler);void handle(Object handler);
}public class AnnotationHandlerAdapter implements HandlerAdapter{Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof AnnotationController);}Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((AnnotationController)handler).doAnnotationHandler();}
}public class HttpHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof HttpController);}Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((HttpController)handler).doHttpHandler();}
}public class SimpleHandlerAdapter implements HandlerAdapter{Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof SimpleController);}Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((SimpleController)handler).doSimpleHandler();}
}//DispatcherServlet类 执行整体逻辑
public class DispatchServlet {public static ListHandlerAdapter handlerAdapters new ArrayListHandlerAdapter();//注内置的处理器适配器也可以自定义然后注册到DispatcherServlet类中public DispatchServlet() {handlerAdapters.add(new AnnotationHandlerAdapter());handlerAdapters.add(new HttpHandlerAdapter());handlerAdapters.add(new SimpleHandlerAdapter());}public void doDispatch() {/** 1、这里用来调用handlermapping获取对应的controller(handler)* springmvc中默认使用的是 RequestMappingHandlerMapping*/AnnotationController annotationController new AnnotationController();//2、通过controller(handler)选择对应的handlerAdapterHandlerAdapter handlerAdapter getHandler(annotationController);//3、调用对应处理程序(controller的方法)处理请求handlerAdapter.handle(annotationController);}public HandlerAdapter getHandler(Controller controller) {for (HandlerAdapter handlerAdapter : handlerAdapters) {if(handlerAdapter.supports(controller)) {return handlerAdapter;}}return null;}
}//客户端
public class Client {public static void main(String[] args) {new DispatchServlet().doDispatch();}
}自定义适配器
要自定义一个 HandlerAdapter你需要实现 org.springframework.web.servlet.HandlerAdapter 接口并提供对你的自定义处理器的支持。下面是一个简单的自定义 HandlerAdapter 示例
首先创建一个自定义处理器
public class CustomHandler {public String handleRequest() {return Hello, CustomHandler!;}
}接着实现一个自定义的 HandlerAdapter
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomHandlerAdapter implements HandlerAdapter {Overridepublic boolean supports(Object handler) {return handler instanceof CustomHandler;}Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {CustomHandler customHandler (CustomHandler) handler;String result customHandler.handleRequest();return new ModelAndView(customView, message, result);}Overridepublic long getLastModified(HttpServletRequest request, Object handler) {return -1;}
}要在 Spring MVC 应用中使用这个自定义的 HandlerAdapter你需要将其注册到 DispatcherServlet 中。在基于 Java 配置的应用中你可以这样做
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {Overrideprotected void addAdapters(ListHandlerAdapter adapters) {adapters.add(new CustomHandlerAdapter());super.addAdapters(adapters);}
}这样你的自定义 HandlerAdapter 就会在 Spring MVC 应用中生效并能处理 CustomHandler 类型的处理器。
5.2 AOP
在Spring的Aop中使用Advice通知来增强被代理类的功能Advice的类型有BeforeAdvice、AfterReturningAdvice、ThreowSadvice。
每种Advice都有对应的拦截器MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。
各种不同类型的Interceptor通过适配器统一对外提供接口如下类图所示client — target — adapter — interceptor — advice。最终调用不同的advice来实现被代理类的增强 原理springmvc类似