知识大全 处理不合适的依赖
Posted 知
篇首语:所谓一见钟情不过见色起意,所谓日久生情不过权衡利弊。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 处理不合适的依赖相关的知识,希望对你有一定的参考价值。
摘要
要判断一个代码是不是包含了 不合适的依赖 共有四个方法 看代码 有没有互相依赖? 认真想想 它真正需要的是什么? 推测一下 它在以后的系统中可以重用吗? 到要重用的时候就知道了 现在我要重用这个类 能不能重用?
如果现在有一个类Parent 里面有个属性的类型是Child add的方法里面还有个参数的类型是Girl
class Parent Child child; void add(Girl girl)
因为上面Parent里面用到了Child跟Girl这两个类 我们就说 Parent引用了类Child跟类Girl 现在的问题是 如果Child这个类或者Girl这个类编译不过的话 那么Parent这个类也编译不了了 也就是说 Parent依赖于Child跟Girl 这章讲述的 就是因为一些类的依赖造成的无法重用的问题 示例 这是一个处理ZIP的程序 用户可以在主窗口中先输入要生成的目标zip的路径 比如c:\\f zip 然后输入他想压缩到这个zip的源文件的路径 比如c:\\f doc和c:\\f doc 然后这个程序就会开始压缩f doc和f doc 生成f zip文件 在压缩各个源文件的时候 主窗口下的状态栏都要显示相关的信息 比如 在压缩c:\\f doc的时候 状态栏就显示 正在压缩 c:\\f zip 目前的代码就是
class ZipMainFrame extends Frame StatusBar sb; void makeZip() String zipFilePath; String srcFilePaths[]; //根据UI上给zipFilePath和srcFilePaths赋值 ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths this); void setStatusBarText(String statusText) sb setText(statusText); class ZipEngine void makeZip(String zipFilePath String srcFilePaths[] ZipMainFrame f) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 f setStatusBarText( Zipping +srcFilePaths[i]);
我们还有一个存货管理系统 里面有一些程序的数据文件 经常需要压缩起来备份 这些源数据文件都有固定的路径 所以就不需要用户特地去输入路径了 现在我们想直接把上面的这个ZipEngine类拿过来重用 这个存货管理系统也有一个主窗口 同样在压缩待备份文件时 状态栏上面也要显示目前正在压缩的文件名称 现在 问题来了 我们希望可以在不用修改代码的情况下直接重用ZipEngine这个类 但看了上面的代码以后我们发现 在调用makeZip这个方法时 还需要一个传递一个ZipMainFrame类型的参数进来 可是很明显我们现在的这个存货管理系统里面并没有ZipMainFrame这样的类 也就是说 现在ZipEngine这个类 在我们的这个存货管理系统中用不了了 再往远一点想 好像其他的系统 一般也不会有ZipMainFrame这个类 即使类名一样的 里面所做的功能也不一样 那其他的系统也重用不了这个ZipEngine类了 不合适的依赖 让代码很难被重用 因为ZipEngine引用了ZipMainFrame这个类 当我们想重用ZipEngine的时候 我们就需要将ZipMainFrame也加进来 调用ZipEngine的makeZip方法时 还要构造一个ZipMainFrame对象传给它 而在新的环境中 我们不可能有一个同样的ZipMainFrame 也不可能特地为了调用这个方法 随便创建一个ZipMainFrame对象给它 一般来说 如果一个类A引用了一个类B 当我们想要重用A这个类时 我们就还得将B这个类也加进我们的系统 如果B引用了C 那么B又将C也一起拉了进来 而如果B或者C在一个新的系统中没有意义 或者压根儿不应该存在的情况下 真正我们想要用的A这个类也用不了了 因此 不合适的依赖 让代码很难被重用 为了可以重用ZipEngine 首先 我们得让ZipEngine不再引用ZipMainFrame 或者说 让ZipEngine不用依赖于ZipMainFrame 那怎么做呢?回答这个问题之前 我们先回答另一个问题 给你一段代码 你怎么判断这段代码是不是包含了 不合适的依赖 ? 不合适 这个词定义的标准又是什么?怎么判断是 不合适的依赖 方法 一个简单的方法就是 我们先看一下这段代码里面有没有一些互相循环的引用 比如 ZipMainFrame引用了ZipEngine这个类 而ZipEngine又引用了ZipMainFrame 我们管这样的类叫 互相依赖 互相依赖也是一种代码异味 我们就认定这样的代码 是 不合适的依赖 这个方法很简单 不过 这种方法并不能包含全部情况 并不是所有有 不合适的依赖 的代码 都是这种互相依赖 方法 另一个方法比较主观 在检查代码的时候 我们问自己 对于它已经引用的这些类 是它真正需要引用的吗?对于ZipEngine 它真的需要ZipMainFrame这个类吗?ZipEngine只是改变ZipMainFrame的状态栏上的信息 是不是只有引用了ZipMainFrame才能满足这样的需求 其他类行不行?有没有一个类可以取代ZipMainFrame呢?而实际上 ZipEngine并不是一定要引用ZipMainFrame的 它想引用的 其实只是一个可以显示信息的状态栏而已 因此 我们就将代码改为
class ZipEngine void makeZip(String zipFilePath String srcFilePaths[] StatusBar statusBar) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 statusbar setText( Zipping +srcFilePaths[i]);
现在 ZipEngine只是引用了StatusBar 而不再是ZipMainFrame了 可是这样好吗?相对好一些!因为StatusBar比较通用(至少有StatusBar这个类的系统比ZipMainFrame多多了) 这样的话 ZipEngine这个类的可重用性就大幅改观了 不过 这样的方法还是太主观了 没有一个既定的标准 可以判断ZipEngine到底需要的是什么样的东西 比如 我们就说 ZipEngine其实想要的也不是一个状态栏 它只是想调用一个可以显示一些信息的接口而已(而不是一个状态栏这么大的一个对象)
方法 第 种方法也很主观 在设计类的时候 我们先预测一个以后可能会重用这个类的系统 然后再判断 在那样的系统中 这个类能不能被重用?如果你自己都觉得以后的系统不能重用这个类的话 你就断定 这个类包含 不合适的依赖 了 比如 我们在设计完ZipEngine这个类时 我们就想一下 这个类能在别的系统重用吗?可是好像别的系统 不会有ZipMainFrame这个类 至少一个没有GUI的系统会有这样的类!这样的话 那它就不应该引用ZipMainFrame这个类了 这个方法其实也很主观 不怎么实用 每个人预测的可能性都不一样 方法 第 个方法比较简单而且客观了 当我们想在一个新系统中重用这个类 却发现重用不了时 我们就判断 这个类包含了 不合适的依赖 比如 我们在存货管理系统中 要重用ZipEngine的时候 我们才发现 这个类重用不了 这时我们就认定 这个类有 不合适的依赖 后一种方法是个 懒惰而被动的 方法 因为我们真正想在具体的项目中重用的时候 才能判断出来 不过这也是个很有效的方法 总结 要判断一个代码是不是包含了 不合适的依赖 共有四个方法 看代码 有没有互相依赖? 认真想想 它真正需要的是什么? 推测一下 它在以后的系统中可以重用吗? 到要重用的时候就知道了 现在我要重用这个类 能不能重用? 方法 跟 是最简单的方法 推荐初学者可以这样来判断 有更多的设计经验了 再用方法 跟 会好一些 怎么让ZipEngine不再引用(依赖于)ZipMainFrame 现在我们来看看 怎么让ZipEngine不再引用ZipMainFrame 其实 在介绍方法 的时候 我们就已经通过思考发现 ZipEngine这个类真正需要的是什么 也找出了解决办法 不过因为方法 相对来讲并不是那么简单就可以用好的 所以我们先假装不知道方法 的结果 我们用方法 现在我们是在做一个文字模式的系统(没有状态栏了 我们只能直接在没有图形的屏幕上显示这些信息) 发现ZipEngine不能重用了 怎么办? 因为我们不能重用ZipEngine 我们只好先将它的代码复制粘贴出来 然后再修改成下面的代码
class TextModeApp void makeZip() String zipFilePath; String srcFilePaths[]; ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths); class ZipEngine void makeZip(String zipFilePath String srcFilePaths[]) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 System out println( Zipping +srcFilePaths[i]);
再看一下原来的代码是
class ZipEngine void makeZip(String zipFilePath String srcFilePaths[] ZipMainFrame f) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 f setStatusBarText( Zipping +srcFilePaths[i]);
很明显 这里面有很多的重复代码(代码异味) 要消除这样的代码异味 我们就先用伪码让这两段代码看起来一样 比如 改成
class ZipEngine void makeZip(String zipFilePath String srcFilePaths[]) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 显示信息
因为 显示信息 具体出来 有两种实现 所以我们现在创建一个接口 里面有一个方法用来显示信息 这个方法可以直接取名为 showMessage 而根据这个接口做的事 我们也可以直接将接口名取为 MessageDisplay 或者 MessageSink 之类的 interface MessageDisplay void showMessage(String msg); 将ZipEngine改为
class ZipEngine void makeZip(String zipFilePath String srcFilePaths[] MessageDisplay msgDisplay) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 msgDisplay showMessage( Zipping +srcFilePaths[i]);
而MessageDisplay这个接口的两个实现类就是
class ZipMainFrameMessageDisplay implements MessageDisplay ZipMainFrame f; ZipMainFrameMessageDisplay(ZipMainFrame f) this f = f; void showMessage(String msg) f setStatusBarText(msg); class SystemOutMessageDisplay implements MessageDisplay void showMessage(String msg) System out println(msg);
现在两个系统也相应的做了修改
class ZipMainFrame extends Frame StatusBar sb; void makeZip() String zipFilePath; String srcFilePaths[]; //根据UI上给zipFilePath和srcFilePaths赋值 ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths new ZipMainFrameMessageDisplay(this)); void setStatusBarText(String statusText) sb setText(statusText); class TextModeApp void makeZip() String zipFilePath; String srcFilePaths[]; ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths new SystemOutMessageDisplay());
改进后的代码下面就是改进完的代码 为了让代码看起来清楚一些 我们用了Java的内类
interface MessageDisplay void showMessage(String msg); class ZipEngine void makeZip(String zipFilePath String srcFilePaths[] MessageDisplay msgDisplay) //在该路径上创建zip文件 for (int i = ; i < srcFilePaths length; i++) //将srcFilePaths[i]的文件加到压缩包中 msgDisplay showMessage( Zipping +srcFilePaths[i]); class ZipMainFrame extends Frame StatusBar sb; void makeZip() String zipFilePath; String srcFilePaths[]; //根据UI上给zipFilePath和srcFilePaths赋值 ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths new MessageDisplay() void showMessage(String msg) setStatusBarText(msg); ); void setStatusBarText(String statusText) sb setText(statusText); class TextModeApp void makeZip() String zipFilePath; String srcFilePaths[]; ZipEngine ze = new ZipEngine(); ze makeZip(zipFilePath srcFilePaths new MessageDisplay() void showMessage(String msg) System out println(msg); );
cha138/Article/program/Java/hx/201311/26899相关参考
针对女性患白癜风抹哪种药合适这个问题,皮肤病相关专家告诉我们,多数的外用涂抹类西药中都含有激素的成分,患者不应当过分的依赖,还需要根治为宜。至于应涂抹哪种药,还要根据患者的白斑面积大小以及病情的长短还
Web请求异步处理降低应用依赖风险 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 问题凸现&nb
公文的形成与发挥作用需依赖于_____。A、公文处理B、收文办理C、发文办理D、办毕公文答案:A解析:公文的形成与发挥作用需依赖于公文处理。故本题答案选A
近年,常有农民反映花生田蛴螬比较难治。笔者认为造成蛴螬难治的原因有以下几点:一是防治适期掌握不准,防治方法单一,过于依赖化学药剂灌根防治。 二是选用土壤类型不合适。据调查,在黏土地和壤土地的地块发生
近年,常有农民反映花生田蛴螬比较难治。笔者认为造成蛴螬难治的原因有以下几点:一是防治适期掌握不准,防治方法单一,过于依赖化学药剂灌根防治。 二是选用土壤类型不合适。据调查,在黏土地和壤土地的地块发生
孩子不爱上幼儿园怎么办,特别依赖妈妈!很多小孩子都是这样,前期只能狠狠心,没办法的。我朋友家的哭了三月幼儿园特别依赖妈妈的孩子评语刚刚开始孩子是这样子,就是看着来就在门口迎接孩子,说孩子乖,抱过来亲一
在讨论物质依赖之前,必须先介绍一下什么是物质滥用,因为两者有密切的联系。物质滥用是指违反社会常规或与公认的医疗实践不相关或不一致地间断或持续过度使用精神活性物质的现象。这种滥用远非尝试性使用、社会娱乐
在讨论物质依赖之前,必须先介绍一下什么是物质滥用,因为两者有密切的联系。物质滥用是指违反社会常规或与公认的医疗实践不相关或不一致地间断或持续过度使用精神活性物质的现象。这种滥用远非尝试性使用、社会娱乐
苯丙胺类兴奋剂(ATS)可以产生精神依赖,但与海洛因、大麻等毒品不同,在突然停吸后常不会产生像阿片类、酒类出现严重的躯体戒断症状。对于ATS的戒断及毒性症状,只需对症处理。 ①精神症状的治疗:ATS
苯丙胺类兴奋剂(ATS)可以产生精神依赖,但与海洛因、大麻等毒品不同,在突然停吸后常不会产生像阿片类、酒类出现严重的躯体戒断症状。对于ATS的戒断及毒性症状,只需对症处理。 ①精神症状的治疗:ATS