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

如果这个世界没有了项目经理,事情的发展可能并不会如同想象中一样美好,相反,对于开发人员来说可能是噩梦的开始。
比如:
客户因为几个需求的具体实现大发雷霆,甚至开始恶语相向,一通含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{@Overridepublic int skill() {int anger = communicate();return anger/1000;}
}

开发人员

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

分析

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


对象适配器

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

在这里插入图片描述

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

图解

在这里插入图片描述

实例核心

public class ProjectManager implements Manage {private Customer customer;public ProjectManager(Customer customer){this.customer = customer;}@Overridepublic 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/652627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理:transfomer架构

介绍 transfomer是自然语言处理中的一个重要神经网络结构&#xff0c;算是在传统RNN和LSTM上的一个升级&#xff0c;接下来让我们来看看它有处理语言序列上有哪些特殊之处 模型整体架构 原论文中模型的整体架构如下&#xff0c;接下来我们将层层解析各层的作用和代码实现 该…

3d模型怎么分辨材质?--模大狮模型网

在3D模型中&#xff0c;通常可以通过以下几种方式来分辨材质&#xff1a; 视觉检查&#xff1a;在3D渲染视图或预览窗口中&#xff0c;您可以直接观察模型的外观来区分不同的材质。不同的材质可能具有不同的颜色、纹理、反射率等特征&#xff0c;因此通过直观的视觉检查&#x…

LV老板重夺全球首富 再次超过马斯克;新东方安徽总部大厦启用;中国与泰国签署互免签证协定

今日精选 • LV老板重夺全球首富 再次超过马斯克• 新东方安徽总部大厦启用• 中国与泰国签署互免签证协定 投融资与企业动态 • ​​传Temu将于3月在美国上线半托管业务• 国内数字支付解决方案提供商 “连连数字” 估值150亿&#xff0c;即将IPO• 滴滴与宁德时代宣布成立…

深度强化学习(王树森)笔记05

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

安全防御{第三次作业(在第二次作业上添加点需求)}

目录 需求&#xff1a; 拓扑图&#xff1a; 注意&#xff1a;先打开防火墙web界面&#xff0c;在此不做演示 1.要求一&#xff1a;&#xff0c;生产区在工作时间内可以访问服务器区&#xff0c;仅可以访问http服务器 2.要求二&#xff1a;办公区全天可以访问服务器区&#…

BGP:03 BGP路由

这是实验拓扑&#xff0c;IBGP 利用环回口建立邻居&#xff0c;IGP 协议为 OSPF&#xff0c; EBGP 通过物理接口建立邻居 基本配置&#xff1a; R1: sys sysname R1 int loop 0 ip add 1.1.1.1 24 int g0/0/0 ip add 192.168.12.1 24 qR2: sys sysname R2 int loop 0 ip ad…

JCEF学习

JCEF重要概念 CEF CEF&#xff0c;全称Chromium Embedded Framework &#xff0c;它是基于Google Chromium的开源项目&#xff0c;它的目标是能够向第三方程序添加WEB浏览器功能&#xff0c;以及可以使用HTML、CSS和JS渲染界面。 CEF框架是由Marshall Greenblatt 在 2008 年创…

第17节-高质量简历写作求职通关-投递反馈

&#xff08;点击即可收听&#xff09; 投递跟进和感谢信 如果对一家公司特别心仪&#xff0c;但是投递简历后一直得不到回复怎么办&#xff1f; 面试之后觉得自己没有表现好怎么办&#xff1f; 面试完几天了&#xff0c;依然没有得到回应怎么办&#xff1f; 这个时候你需要写一…

八种Flink任务告警方式

目录 一、Flink应用分析 1.1 Flink任务生命周期 1.2 Flink应用告警视角分析 二、监控告警方案说明 2.1 监控消息队中间件消费者偏移量 2.2 通过调度系统监控Flink任务运行状态 2.3 引入开源服务的SDK工具实现 2.4 调用FlinkRestApi实现任务监控告警 2.5 定时去查询目标…

无人机在三维空间中的转动问题

前提 这篇博客是对最近一个有关无人机拍摄图像项目中所学到的新知识的一个总结&#xff0c;比较杂乱&#xff0c;没有固定的写作顺序。 无人机坐标系旋转问题 上图是无人机坐标系&#xff0c;绕x轴是翻滚(Roll)&#xff0c;绕y轴是俯仰(Pitch)&#xff0c;绕z轴是偏航(Yaw)。…

力扣日记1.27-【回溯算法篇】131. 分割回文串

力扣日记&#xff1a;【回溯算法篇】131. 分割回文串 日期&#xff1a;2023.1.27 参考&#xff1a;代码随想录、力扣 131. 分割回文串 题目描述 难度&#xff1a;中等 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可…

D. Epic Transformation(堆+贪心)

思路&#xff1a;我们删的策略是从次数多的数开始删&#xff0c;每次取两种不同的数&#xff0c;每种删去一个&#xff0c;然后放回堆中。 代码&#xff1a; void solve(){int n;cin >> n;map<int,int>mp;for(int i 1;i < n;i ){int x;cin >> x;mp[x] …

Java笔记 --- 四、异常

四、异常 Java.lang.Throwable Error Exception&#xff08;异常&#xff09; 异常的作用 异常的处理方式 JVM默认的处理方式 捕获异常&#xff08;自己处理&#xff09; try里面没有出现异常&#xff0c;就不会运行catch里面的代码 如果出现多个异常&#xff0c;需要多个c…

【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数

本文涉及知识点 动态规划汇总 图论 深度游戏搜索 归并排序 组合 LeetCoce1569将子数组重新排序得到同一个二叉搜索树的方案数 给你一个数组 nums 表示 1 到 n 的一个排列。我们按照元素在 nums 中的顺序依次插入一个初始为空的二叉搜索树&#xff08;BST&#xff09;。请你统…

精选6款前端动画特效分享(附在线演示)

分享6款好玩的前端动画特效 其中有CSS动画、canvas动画、js小游戏等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 CSS日食与太阳碰撞动画 一款基于CSS实现的日食动画特效 碰撞物体会从右侧旋转向太阳靠近重合而后…

程序员成被裁最多的职业,互联网成围城,“转码”神话破灭?

随着互联网蓬勃发展&#xff0c;“转码”一直被视为找不到工作时的灵丹妙药。所谓转码&#xff0c;就是转行成为程序员。专业太偏&#xff1f;没关系&#xff0c;可以转码。失业了&#xff1f;没关系&#xff0c;可以转码。不知道该做什么工作&#xff1f;那就转码吧。程序员薪…

idea提交代码到git或svn上时,怎么忽略.class、.iml文件和文件夹等不必要的文件

第一种方法 在Setings–> Editor --> File Types -->Ignore files and folders中添加需要忽略的文件和文件夹&#xff1a; .idea 忽略 .idea 的文件或者文件夹 *.iml 忽略后缀为iml的文件 target 忽略target 文件或目录以及目录下的所有文件注…

Linux学习之文件系统与动静态库

目录 一&#xff0c;文件的管理 什么是磁盘&#xff1f; 磁盘的逻辑抽象结构 格式化 inode 挂载 软硬链接 二&#xff0c;动静态库 什么是动静态库&#xff1f; 1.站在库的制作者角度 静态库&#xff1a; 制作一个静态库 2.站在静态库使用者的角度 动态库 作为制…

80.网游逆向分析与插件开发-背包的获取-自动化助手显示物品数据1

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;升级Notice类获得背包基址-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;3be017de38c50653b…

操作日志应记录编辑的前后内容变化

总体思路是增加一个注解类&#xff0c;将注解加到要进行记录变化的Java类属性上却可。 上代码&#xff1a; 1. 实现注解类&#xff1a; Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) public interface FieldName {String value();boolean isIgnoreNull()…