怎么实现代码的重用性?_代码重用分析报告范文-程序员宅基地

技术标签: Java  继承  代码重用  

措施一:

改写类的实例方法 通过类继承实现代码重用不是精确的代码重用技术,因此它并不是最理想的代码重用机制。换句话说,如果不继承整个类的所有方法和数据成员,我们无法重用该类里面的单个方法。继承总是带来一些多余的方法和数据成员,它们总是使得重用类里面某个方法的代码复杂化。另外,派生类对父类的依赖关系也使得代码进一步复杂化:对父类的改动可能影响子类;修改父类或者子类中的任意一个类时,我们很难记得哪一个方法被子类覆盖、哪一个方法没有被子类覆盖;最后,子类中的覆盖方法是否要调用父类中的对应方法有时并不显而易见。 任何方法,只要它执行的是某个单一概念的任务,就其本身而言,它就应该是首选的可重用代码。为了重用这种代码,我们必须回归到面向过程的编程模式,把类的实例方法移出成为全局性的过程。为了提高这种过程的可重用性,过程代码应该象静态工具方法一样编写:它只能使用自己的输入参数,只能调用其他全局性的过程,不能使用任何非局部的变量。这种对外部依赖关系的限制简化了过程的应用,使得过程能够方便地用于任何地方。当然,由于这种组织方式总是使得代码具有更清晰的结构,即使是不考虑重用性的代码也同样能够从中获益。 在Java中,方法不能脱离类而单独存在。为此,我们可以把相关的过程组织成为独立的类,并把这些过程定义为公用静态方法。 例如,对于下面这个类: class Polygon {..
public int getPerimeter() {…}
public boolean isConvex() {…}
public boolean containsPoint(Point p) {…}..}我们可以把它改写成:
public int getPerimeter() {return pPolygon.computePerimeter(this);}
public boolean isConvex() {return pPolygon.isConvex(this);}
public boolean containsPoint(Point p) {return pPolygon.containsPoint(this, p);}.}其中,pPolygon是:
class pPolygon {
static public int computePerimeter(Polygon polygon) {…}
static public boolean isConvex(Polygon polygon) {…}
static public boolean
containsPoint(Polygon polygon, Point p) {…}
} 从类的名字pPolygon可以看出,该类所封装的过程主要与Polygon类型的对象有关。名字前面的p表示该类的唯一目的是组织公用静态过程。在Java中,类的名字以小写字母开头是一种非标准的做法,但象pPloygon这样的类事实上并不提供普通Java类的功能。也就是说,它并不代表着一类对象,它只是Java语言组织代码的一种机制。 在上面这个例子中,改动代码的最终效果是使得应用Polygon功能的客户代码不必再从Polygon继承。Polygon类的功能现在已经由pPolygon类以过程为单位提供。客户代码只使用自己需要的代码,无需关心Polygon类中自己不需要的功能。但它并不意味着在这种新式过程化编程中类的作用有所削弱。恰恰相反,在组织和封装对象数据成员的过程中,类起到了不可或缺的作用,而且正如本文接下来所介绍的,类通过多重接口实现多态性的能力本身也带来了卓越的代码重用支持。然而,由于用实例方法封装代码功能并不是首选的代码重用手段,所以通过类继承达到代码重用和多态性支持也不是最理想的。

措施二:

把参数类型改成接口 正如Allen Holub在《Build User Interfaces for Object-Oriented Systems》中所指出的,在面向对象编程中,代码重用真正的要点在于通过接口参数类型利用多态性,而不是通过类继承: “……我们通过对接口而不是对类编程达到代码重用的目的。如果某个方法的所有参数都是对一些已知接口的引用,那么这个方法就能够操作这样一些对象:当我们编写方法的代码时,这些对象的类甚至还不存在。从技术上说,可重用的是方法,而不是传递给方法的对象。” 在“措施一”得到的结果上应用Holub的看法,当某块代码能够编写为独立的全局过程时,只要把它所有类形式的参数改为接口形式,我们就可以进一步提高它的可重用能力。经过这个改动之后,过程的参数可以是实现了该接口的所有类的对象,而不仅仅是原来的类所创建的对象。由此,过程将能够对可能存在的大量的对象类型进行操作。 例如,假设有这样一个全局静态方法: static public boolean contains(Rectangle rect, int x, int y) {…} 这个方法用于检查指定的点是否包含在矩形里面。在这个例子中,rect参数的类型可以从Rectangle类改变为接口类型,如下所示:static public boolean contains(Rectangular rect, int x, int y) {…} 而Rectangular接口的定义是:public interface Rectangular {Rectangle getBounds();} 现在,所有可以描述为矩形的类(即,实现了Rectangular接口的类)所创建的对象都可以作为提供给pRectangular.contains()的rect参数。通过放宽参数类型的限制,我们使方法具有更好的可重用性。 不过,对于上面这个例子,Rectangular接口的getBounds方法返回Rectangle,你可能会怀疑这么做是否真正值得。换言之,如果我们知道传入过程的对象会在被调用时返回一个Rectangle,为什么不直接传入Rectangle取代接口类型呢?之所以不这么做,最重要的原因与集合有关。让我们假设有这样一个方法:static public boolean areAnyOverlapping(Collection rects) {…} 该方法用于检查给定集合中的任意矩形对象是否重叠。在这个方法的内部,当我们用循环依次访问集合中的各个对象时,如果我们不能把对象cast成为Rectangular之类的接口类型,又如何能够访问对象的矩形区域呢?唯一的选择是把对象cast成为它特有的类形式(我们知道它有一个方法可以返回矩形),它意味着方法必须事先知道它所操作的对象类型,从而使得方法的重用只限于那几种对象类型。而这正是前面这个措施力图先行避免的问题!

措施三:

选择最简单的参数接口类型 在实施第二个措施时,应该选用哪一种接口类型来取代给定的类形式?答案是哪一个接口完全满足过程对参数的需求,同时又具有最少的多余代码和数据。描述参数对象要求的接口越简单,其他类实现该接口的机会就越大——由此,其对象能够作为参数使用的类也越多。从下面这个例子可以很容易地看出这一点:static public boolean areOverlapping(Window window1, Window window2) {…} 这个方法用于检查两个窗口(假定是矩形窗口)是否重叠。如果这个方法只要求从参数获得两个窗口的矩形坐标,此时相应地简化这两个参数是一种更好的选择:static public boolean areOverlapping(Rectangular rect1, Rectangular rect2) {…} 上面的代码假定Window类型实现了Rectangular接口。经过改动之后,对于任何矩形对象我们都可以重用该方法的功能。 有些时候可能会出现描述参数需求的接口拥有太多方法的情况。此时,我们应该在全局名称空间中定义一个新的公共接口供其他面临同一问题的代码重用。 当我们需要象使用C语言中的函数指针一样使用参数时,创建唯一的接口描述参数需求是最好的选择。例如,假设有下面这个过程:static public void sort(List list, SortComparison comp) {…} 该方法运用参数中提供的比较对象comp,通过比较给定列表list中的对象排序list列表。sort对comp对象的唯一要求是要调用一个方法进行比较。因此,SortComparison应该是只带有一个方法的接口:public interface SortComparison {boolean comesBefore(Object a, Object b);} SortComparison接口的唯一目的在于为sort提供一个它所需功能的钩子,因此SortComparison接口不能在其他地方重用。 总而言之,本文三个措施适合于改造现有的、按照面向对象惯例编写的代码。这三个措施与面向对象编程技术结合就得到了一种可在以后编写代码时使用的新式代码编写技术,它能够简化方法的复杂性和依赖关系,同时提高方法的可重用能力和内部凝聚力。 当然,这里的三个措施不能用于那些天生就不适合重用的代码。不适合重用的代码通常出现在应用的表现层。例如,创建程序用户界面的代码,以及联结到输入事件的控制代码,都属于那种在程序和程序之间千差万别的代码,这种代码几乎不可能重用。

主要是:1:不要有hardcode;2:能用接口、抽象类不用具体类;3:写代码时框架和具体业务要尽可能分离,所以呢,主要是一个“分”字,所有的模式呀,经典例子呀,都是分的很巧妙,看你怎么分离你的代码了

*

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zsyoung/article/details/52813689

智能推荐

mui app 显示手机任务栏_mui 后台显示通知栏-程序员宅基地

文章浏览阅读276次。manifest.json plus里加上"statusbar" : { "immersed" : true, "background" : "#D74B28" },同时基础配置里是否应用全屏不进行勾选..._mui 后台显示通知栏

Appium基础篇6-抓元素工具之Android Device Monitor_android中使用monitor抓布局-程序员宅基地

文章浏览阅读401次。 上一篇,我们介绍了如何使用UI Automator Viewer这个工具来获取安卓上app的页面元素的信息。除了UI Automator Viewer之外,其实Android SDK下还有一个工具支持来抓取元素的属性,这个工具叫Android Device Monitor,简称DDMS,也在tools文件夹下。1.进入SDK安装目录2.点击Monitor.bat点击后,默认页面如下图。3...._android中使用monitor抓布局

GitHub开源项目之“线程池”_thread-pool-c github-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏5次。Table of ContentsA simple C thread pool implementationPossible enhancements原理代码threadpool.hthreadpool.c测试例:heavy.cshutdown.cthrdtest.cA simple C thread pool implementationCurre..._thread-pool-c github

MCPD认证 Web开发者认证考试科目及升级-程序员宅基地

文章浏览阅读120次。MCPD认证 Web开发者简称:MCPD: webdev全称:MCPD: Web DeveloperMCPD:webdev认证考试科目 (1门+2门MCTS考试) 认证考试 培训课程 参考资料 70–547: P..._asp.net and/or mcpd: web developer

用 Markdown 快速生成漂亮的 Latex 伪代码_伪代码生成工具-程序员宅基地

文章浏览阅读6.8k次,点赞11次,收藏24次。组合: **VSCode** + **Markdown Preview Enhanced** + **pseudocode.js** _伪代码生成工具

Linux学习总结(压缩解压、磁盘分区、格式化、挂载、进程管理命令、服务管理、RPM软件包管理、YUM软件包管理、文本编辑器)_4、linux查看硬盘的命令?如何分区?压缩和解压文件命令-程序员宅基地

文章浏览阅读672次。学习Linux的压缩解压、磁盘分区、格式化、挂载、进程管理命令、服务管理、RPM软件包管理、YUM软件包管理、文本编辑器_4、linux查看硬盘的命令?如何分区?压缩和解压文件命令

随便推点

uni-app 系统状态栏高度CSS变量--status-bar-height-程序员宅基地

文章浏览阅读1.1k次。【代码】uni-app 系统状态栏高度CSS变量--status-bar-height。_--status-bar-height

【日积月累】SpringBoot 通过注解@CacheConfig @Cacheable @CacheEvict @CachePut @Caching使用缓存-程序员宅基地

文章浏览阅读1k次。Spring在3.1版本,就提供了一条基于注解的缓存策略,实际使用起来还是很丝滑的,本文将针对几个常用的注解进行简单的介绍说明,有需要的小伙伴可以尝试一下@CacheConfig:常用于类级别的注解,用于统一配置类缓存的公共属性@Caching:可以在一个类或方法同时使用多个缓存相关注解,灵活配置缓存策略@Cacheable:用于标记一个类或方法,当被标记对象被访问,会先去缓存中查询相应的结果,如果存在则返回,不存在则指向方法@CacheEvict :用于从缓存中移除数据。_@cacheconfig

javamail 给多人发送邮件_javax.mai邮件群发-程序员宅基地

文章浏览阅读1.9w次,点赞2次,收藏14次。之前测试mail这个功能的时候,简单的作出了发送email的功能,但是仅仅发给一个人可以,发送多个联系人就会出错,发送失败!请与邮件管理员联系。 javax.mail.internet.AddressException: Illegal whitespace_javax.mai邮件群发

软考高项:项目进度管理模拟试题_某项目包含a、b、c、d、e、f、g七个活动,各活动的历时估算和活动间的逻辑关系如下-程序员宅基地

文章浏览阅读3.8k次。活动D和活动F只能在活动C结束后开始.活动A和活动B可以在活动C开始后的任何时间内开始,但是必须在项目结束前完成.活动E只能在活动D完成后开始.活动B是在活动C开始1天后才开始的.在活动B的过程中,发生了一件意外事件,导致活动B延期2天.为了确保项目按时完成,______.40.完成某信息系统集成项目中的一个最基本的工作单元A所需的时间,乐观的估计需8天,悲观的估计需38天,最可能的估计需20天,按照PERT方法进行估算,项目的工期应该为______,在26天以后完成的概率大致为______._某项目包含a、b、c、d、e、f、g七个活动,各活动的历时估算和活动间的逻辑关系如下

web集群学习:nginx+keepalived实现负载均衡高可用性-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏2次。​在Keepalived+ Nginx 高可用负载均衡架构中,keepalived 负责实现高可用。它是一个高性能的服务器高可用或者热备解决方案,Keepalived主要来防止服务器单点故障的发生问题,可以通过其与Nginx的配合实现Web服务器端的高可用。使用keepalived可以保证nginx的高可用,他能监控nginx的健康状态,当nginx出现宕机时自动主备切换。​_nginx+keepalived实现负载均衡

Java学习【类加载器ClassLoader】_java classloader 加载类-程序员宅基地

文章浏览阅读344次,点赞3次,收藏4次。跟着大佬们的文章学习,这次再深入学习一下类加载器文章目录一、简介:二、类文件的编译过程三、类加载器引导类加载器(BootstrapClassLoader)扩展类加载器(ExtensionsClassLoader)应用类加载器/系统类加载器(AppClassLoader)自定义类加载器(UserDefineClassLoader)四、双亲委派机制五、双亲委派机制的好处六、CLassLoader类核心方法6.1:`loadClass(String)`——加载指定的Java类6.2:`findClass(Str_java classloader 加载类