主页 > 人工智能  > 

12.从项目经理的生存哲学到适配器模式(AdapterPattern)


如果这个世界没有了项目经理,事情的发展可能并不会如同想象中一样美好,相反,对于开发人员来说可能是噩梦的开始。 比如: 客户因为几个需求的具体实现大发雷霆,甚至开始恶语相向,一通含ma量极高的“斯伯坦语”下来,瞬间让性情耿直的开发人员集体开团,场面一度难以控制。因为对于大多数技术部门的人员来说,这种过度“世俗”的沟通方式并不能被接受。 但如果此时有一个经验丰富的项目经理作为缓冲夹在中间,将客户的“斯伯坦语”过滤处理成纯粹的需求,传达给技术人员,再将技术人员的解决方案加以“怀柔的”修饰传递给客户。世界是不是就变得美好了呢? 语言是门艺术,沟通充满了技巧。


一言

适配器模式即:将某个类的接口转换成客户端期望的另一个接口表示,让原本不匹配的两个对象可以协同工作。


概述

在刚刚的例子中,项目经理实际上就是充当了适配器的角色,让原本水火不容的客户和技术人员能够携起手来,共同完成项目。其核心在于适配器的兼容性。 在软件设计领域,通常将适配器模式划分为结构型模式的一种。从用户的角度来看,是看不到被适配者的,就比如客户通常不会关心技术人员的存在,从这个角度来说,整体的结构的耦合度是很低的。用户调用适配器,适配器再调用被适配者。 在适配器的具体实现上,通常有:类适配器、对象适配器、接口适配器三种。


类适配器

项目经理: 客户就是我的爸爸!

参照我们此前描述的情景,项目经理(适配器类)需要将客户类(被适配对象)当作父亲,通过继承获得客户的初始需求,同时还要掌握一定管理能力(实现管理接口),通过管理能力将客户的需求进行处理,交付给开发人员。

图解

实例

我们假定客户的每一个需求都带有一个愤怒值,当这个愤怒值高于10时,开发人员将认位自己受到了冒犯并拒绝工作,而项目经理则需要即时的将客户的需求通过处理交付给开发人员,以期工作的正常开展。 客户

public class Customer { public int communicate(){ int anger = 10000; System.out.println("沟通需求,愤怒指数:"+anger); return anger; } }

管理能力

public interface Manage { public int skill(); }

项目经理

public class ProjectManager extends Customer implements Manage{ @Override public int skill() { int anger = communicate(); return anger/1000; } }

开发人员

public class Devops { public void work(Manage manage){ if (manage.skill()>10) System.out.println("你的态度让我无法工作"); else System.out.println("沟通方式很尊重我,工作包在我身上"); } } 分析

Java是单继承机制,所以类适配器需要继承客户类这一点算是一个缺点,因为这要求管理能力必须是接口,有一定局限性; 客户类的方法在Adapter(项目经理)中都会暴露出来,也增加了使用的成本。由于其继承了客户类,所以它可以根据需求重写客户类的方法,使得Adapter的灵活性增强了。


对象适配器

项目经理:客户不是我的爸爸,他是我的家人。我们彼此尊重、方向一致。

实际上我们已经清楚的看到了类适配器存在的问题:项目经理的膝盖太软了,一直把客户(被适配对象)当作自己的父亲,这使得整个结构存在着很大的局限性。 对象适配的思路上就是让项目经理站起来,不是直接继承客户,而是通过持有客户的对象来解决兼容问题。

图解

实例核心 public class ProjectManager implements Manage { private Customer customer; public ProjectManager(Customer customer){ this.customer = customer; } @Override public int skill() { int anger = customer.communicate(); return anger/1000; } } 分析

对象适配器和类适配器其实算是同一种思想,只不过实现方式不同根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承被适配对象的局限性问题,也不再要求适配能力必须是接口。 使用成本更低,结构上也更灵活。


接口适配器

有很多资料也将这种方式称为“缺省适配器模式”,顾名思义,当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现 (空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。 这其实非常适用于一个接口不想使用其所有方法的情况。 这种方式很容易理解,这里不过多赘述。


适配器模式在SpringMVC源码的应用

相信有的朋友看到SpringMVC再结合我们上文讲到的适配器模式(Adapter)就已经恍然大悟了。SpringMVC框架中一个非常重要的角色就是HandlerAdapter。 我们可以回想一下SpringMVC的工作过程(这里不做展开,忘记了的同学可以查阅下相关资料),其中有一个重要环节就是DispatchServlet 会根据 收到的Handler 选择一个合适的HandlerAdapter。这里就是适配器模式的关键应用。 下面我将相关源码主体剥离了一部分出来,大家可以体会下。

部分源码

Controller

public interface Controller { } class HttpController implements Controller { public void doHttpHandler() { System.out.println("http..."); } } class SimpleController implements Controller { public void doSimplerHandler() { System.out.println("simple..."); } } class AnnotationController implements Controller { public void doAnnotationHandler() { System.out.println("annotation..."); } }

HandlerAdapter

public interface HandlerAdapter { public boolean supports(Object handler); public void handle(Object handler); } class SimpleHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((SimpleController) handler).doSimplerHandler(); } public boolean supports(Object handler) { return (handler instanceof SimpleController); } } class HttpHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((HttpController) handler).doHttpHandler(); } public boolean supports(Object handler) { return (handler instanceof HttpController); } } class AnnotationHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((AnnotationController) handler).doAnnotationHandler(); } public boolean supports(Object handler) { return (handler instanceof AnnotationController); } }

DispatchServlet

public class DispatchServlet { public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>(); public DispatchServlet() { handlerAdapters.add(new AnnotationHandlerAdapter()); handlerAdapters.add(new HttpHandlerAdapter()); handlerAdapters.add(new SimpleHandlerAdapter()); } public void doDispatch() { HttpController controller = new HttpController(); // AnnotationController controller = new AnnotationController(); //SimpleController controller = new SimpleController(); HandlerAdapter adapter = getHandler(controller); adapter.handle(controller); } public HandlerAdapter getHandler(Controller controller) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(controller)) { return adapter; } } return null; } public static void main(String[] args) { new DispatchServlet().doDispatch(); // http... } } 图解

分析

对于多种Controller,应该有对应的适配器对其做处理。 在DispatchServlet从request中取到handler对象后,适配器可以得到自己希望的Controller进而通过getHandler方法得到对应的适配器,在通过适配器执行handle,也就能执行对应controller的对应方法了。


好啦,希望通过此文能让大家对适配器模式有更深一步的认识,也期待获得大家的指正或共鸣。 关注我,共同进步,每周至少一更。——Wayne

标签:

12.从项目经理的生存哲学到适配器模式(AdapterPattern)由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“12.从项目经理的生存哲学到适配器模式(AdapterPattern)