【设计模式】 您所在的位置:网站首页 策略模式和适配器模式的区别 【设计模式】

【设计模式】

2024-07-13 04:20| 来源: 网络整理| 查看: 265

前言

前面的博文我们已经分别讲述了代理模式,策略模式和委派模式各自的使用及案例实现。

但是三者都写完了,我发现其实我自己都有些混淆了,所以今天特意把他们放在一起看看究竟有什么区别和联系

策略模式:

策略模式是对算法的封装。定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

场景:

Spring中Aop代理策略createAopProxy(下文讲解)Spring的对象实例化策略InstantiationStrategy 委派模式:

委派模式的基本作用就是负责任务的调度和分配任务

场景:

类加载的双亲委派机制SpringMVC的DispatcherServletSpring中bean解析的BeanDefinitionParserDelegate 代理模式:

代理模式为其他对象提供一种代理以控制对这个对象的访问

优点: 1、职责清晰。 2、高扩展性。 3、智能化。

缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

场景:

JDK动态代理和CGLIB动态代理Spring的AOP 有什么不同 代理和策略: 简单代理模式中,代理类知道被代理类的行为,因为代理类与被代理类实现的是同一个接口,因此代理类与被代理类的结构是相同的策略模式中,策略容器并不知道内部策略的详细信息,因为容器并没有实现与内部策略相同的接口,即容器与内部策略只是简单的组合关系,容器只是将内部策略的行为抽取出来,进行了统一的实现。 代理和委派: 委派模式的基本目的就是负责任务的调用和分配,和代理模式很像,可以看成是一个特殊的静态代理的全权代理但是代理模式注重过程(),委派模式注重结果(老板不关注任务是怎么完成的,只管把任务交给经理让他去委派调度)。代理模式中,代理类的被代理对象始终不变,而委派模式中委派类的被委托对象可以随时切换。委派模式中委派类相当于全权代理,而不是像代理模式是部分代理也有人理解为代理模式中二者是上下级关系,而委派模式中二者是平级关系 委派和策略: 委派模式中委派者和被委派者实现了同一个接口,策略模式中容器只是算法策略的选择切换所在,不需要实现策略接口 总结

我试着在一个简单的故事中,来举例区分一下这些模式的存在场景(有异议请留言讨论,谢谢)

        前几天公司所在的地方要拆迁,所以只能搬办公室,大家都得帮忙不是,经理也要去深圳出差,就直接告诉HR让她负责,于是HR就开始分配任务,男生负责搬运东西,女生负责清洁,其他的同学就干干杂物,所以搬家公司一把东西搬到新办公室,大家就听HR指挥了,HR看到灯管要换一下,那么这个任务就要交给男生了,看到玻璃脏了,那么这个任务就要交给女生。

        到下午的时候,HR收到了中通快递的短信,可能买了一些新办公室需要的东西,要去快递柜那边拿,我刚好闲着,于是HR把她的短信给我,让我领一下。到了那边,看到快递柜是很大的那种分区的,有中通快递的,有申通快递的,但是取货机是只有一个的,我输了取货码,然后跑到中通快递所在的区,"呯"!,果然这边的快递门开了,好神奇!

分析:

分配任务中,HR是委派者,男生女生是被委派者去取快递时,HR是目标对象,我是代理对象,短信是目标对象的引用取快递中,取货机是容器,不同快递的取货码是不同的算法策略 有什么联系联系

很多设计模式其实在一些优秀的框架中都是混合使用的。

策略和代理: Spring中Aop代理策略

首先看AopProxyFactory接口类提供了createAopProxy接口,这个是策略模式的接口方法。然后DefaultAopProxyFactory实现了该接口作为策略的实现者。然后ProxyCreatorSupport里面引用了AopProxyFactory,并且提供了get,set方法用来运行时改变策略,这里Spring只实现了DefaultAopProxyFactory这一个策略,如果需要自己也可以写个。

策略模式:DefaultAopProxyFactory里面的createAopProxy的逻辑如下,可以在运行时根据参数决定用Cglib策略还是JDK动态代理策略生成代理类:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //如果XML打开了优化开关,或者设置为了代理目标类,或者目前类没有接口 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } //如果有接口,或者通过Proxy.newProxyInstance生成的,则使用jdk动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //使用cglib return new ObjenesisCglibAopProxy(config); } else { //使用jdk动态代理 return new JdkDynamicAopProxy(config); } }

AopProxy也是一个策略接口类,具体实现的策略为(代理模式)JdkDynamicAopProxy,CglibAopProxy,ObjenesisCglibAopProxy

 策略和委派 Spring中的DispatcherServlet

在DispatcherServlet的初始化中有初始化策略方法 ,会使用默认的处理策略HandlerMapping

protected void initStrategies(ApplicationContext context) { //初始化文件上传处理类 initMultipartResolver(context); //初始化本地化Resolver initLocaleResolver(context); //初始化主题Resolver initThemeResolver(context); //初始化一些个预处理的HandlerMappings initHandlerMappings(context); // initHandlerAdapters(context); //初始化异常处理的handler initHandlerExceptionResolvers(context); //初始化请求路径转换为ViewName 的Translator initRequestToViewNameTranslator(context); //初始化ViewResolvers 这个就是针对视图处理的Resolvers 比如jsp处理Resolvers 或者freemarker处理Resolvers initViewResolvers(context); //初始化 主要管理flashmap,比如RedirectAttributes 的属性会放到这个里面,默认使用的是SessionFlashMapManager initFlashMapManager(context); } /** * Initialize the HandlerMappings used by this class. *

If no HandlerMapping beans are defined in the BeanFactory for this namespace, * we default to BeanNameUrlHandlerMapping. */ private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList(matchingBeans.values()); // We keep HandlerMappings in sorted order. OrderComparator.sort(this.handlerMappings); } } else { try { HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerMapping later. } } // Ensure we have at least one HandlerMapping, by registering // a default HandlerMapping if no other mappings are found. if (this.handlerMappings == null) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); } } }

策略模式:从源码中我们可以看到,SpringMVC先会从绑定的ApplicationContext中获取对应的HandlerMapping定义,如果没有取到就会调用getDefaultStrategies(context, HandlerMapping.class)从默认策略中获取。å¨è¿éæå¥å¾çæè¿°

/** * 请求的分发工作 * @param request * @param response */ private void doDispatch(HttpServletRequest request, HttpServletResponse response) { //1.获取用户请求的url String uri = request.getRequestURI(); Handler handler =null; 2、根据uri 去handlerMapping找到对应的hanler for(Handler h :handlerMapping){ if(uri.equals(h.getUrl())){ handler = h; break; } } //3.将具体的任务分发给Method(通过反射去调用其对应的方法) Object obj = null; try { obj = handler.getMethod().invoke(handler.getController(),request.getParameter("mid")); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //4、获取到Method执行的结果,通过Response返回出去 // response.getWriter().write(); }

委派模式:DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制。

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有