`

提高Java代码重用性的三种方法

 
阅读更多

2008年12月8日,第二次COE交流研讨大会。公司总裁兰博士,于副总不辞辛劳,千里迢迢从深圳公司本部赶来武汉主持召开大会,令COE所有员工精神振奋,斗志高昂。会上,兰博士提出了关于COE代码库和代码重用机制的建立。此举即可以减轻学员在COE实训中重复不必要的功能代码的编写使他们可以集中精力主攻项目的精华部分,对于COE项目而言,又是一个不断积累,创新的过程。针对这一点并结合自己的经验,在这里告诉大家三种方法,用于提高Java代码的重用性。

方法一 :改写类的实例方法

通过类继承实现代码重用不是精确的代码重用技术,因此它并不是最理想的代码重用机制。换句话说,如果不继承整个类的所有方法和数据成员,我们无法重用该类里面的单个方法。继承总是带来一些多余的方法和数据成员,它们总是使得重用类里面某个方法的代码复杂化。另外,派生类对父类的依赖关系也使得代码进一步复杂化:对父类的改动可能影响子类;修改父类或者子类中的任意一个类时,我们很难记得哪一个方法被子类覆盖、哪一个方法没有被子类覆盖;最后,子类中的覆盖方法是否要调用父类中的对应方法有时并不显而易见。

任何方法,只要它执行的是某个单一概念的任务,就其本身而言,它就应该是首选的可重用代码。为了重用这种代码,我们必须回归到面向过程的编程模式,把类的实例方法移出成为全局性的过程。为了提高这种过程的可重用性,过程代码应该像静态工具方法一样编写:它只能使用自己的输入参数,只能调用其他全局性的过程,不能使用任何非局部的变量。这种对外部依赖关系的限制简化了过程的应用,使得过程能够方便地用于任何地方。当然,由于这种组织方式总是使得代码具有更清晰的结构,即使是不考虑重用性的代码也同样能够从中获益。

在Java中,方法不能脱离类而单独存在。为此,我们可以把相关的过程组织成为独立的类,并把这些过程定义为公用静态方法。

例如,对于下面这个类:

class Polygon {
public int getPerimeter() {...}
public boolean isConvex() {...}
public boolean containsPoint(Point p) {...}
}

我们可以把它改写成:

class Polygon {
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类中自己不需要的功能。但它并不意味着在这种新式过程化编程中类的作用有所削弱。恰恰相反,在组织和封装对象数据成员的过程中,类起到了不可或缺的作用,而且正如本文接下来所介绍的,类通过多重接口实现多态性的能力本身也带来了卓越的代码重用支持。然而,由于用实例方法封装代码功能并不是首选的代码重用手段,所以通过类继承达到代码重用和多态性支持也不是最理想的。

方法二:把参数类型改成接口

在面向对象编程中,代码重用真正的要点在于通过接口参数类型利用多态性,而不是通过类继承。

当某块代码能够编写为独立的全局过程时,只要把它所有类形式的参数改为接口形式,我们就可以进一步提高它的可重用能力。经过这个改动之后,过程的参数可以是实现了该接口的所有类的对象,而不仅仅是原来的类所创建的对象。由此,过程将能够对可能存在的大量的对象类型进行操作。

例如,假设有这样一个全局静态方法:

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接口不能在其他地方重用。

总而言之,这里介绍的三种方法适合于改造现有的、按照面向对象惯例编写的代码。这三种方法与面向对象编程技术结合就得到了一种可在以后编写代码时使用的新式代码编写技术,它能够简化方法的复杂性和依赖关系,同时提高方法的可重用能力和内部凝聚力。

当然,这里的三种方法不能用于那些天生就不适合重用的代码。不适合重用的代码通常出现在应用的表现层。例如,创建程序用户界面的代码,以及联结到输入事件的控制代码,都属于那种在程序和程序之间千差万别的代码,这种代码几乎不可能重用。希望大家在以后的COE学习过程中,多多练习,编写出规范,实用的代码。


分享到:
评论

相关推荐

    如何提高代码重用性

    在编程领域,代码重用性是提升开发效率和软件质量的关键因素之一。...以上这些策略并不是孤立存在的,而是相互配合,共同作用于提高Java代码的重用性。在实际开发中,开发者应结合具体情况灵活运用,以达到最佳效果。

    关于能提高Java代码可重用性的三个措施

    关于提高Java代码可重用性的三个措施,本文将深入探讨并详细解释这些策略,帮助开发者在实际项目中更好地实现代码的复用。 ### 第一措施:优化类的设计 #### 设计模式的应用 设计模式是软件工程领域的重要概念,...

    基于Java代码重用性的研究.pdf

    代码重用性在软件开发领域是一个古老而又充满活力的话题,尤其是在像Java这样广泛使用的编程语言中,其重要性更是不言而喻。Java语言以其“一次编写,到处运行”的特性,吸引了全球大量的开发人员,而其代码重用性的...

    如何提高java代码的重用性

    本文将介绍三种提高 Java 代码重用性的方法:改写类的实例方法、选择最简单的参数接口类型和把参数类型改成接口。 一、改写类的实例方法 在 Java 中,方法不能脱离类而单独存在。为了提高代码的重用性,我们可以把...

    最大化Java代码可重用性的策略研究.pdf

    为了提高代码重用性,需要确保代码具有高内聚性和低耦合度。内聚性指的是模块内部元素间的关联程度,高的内聚性意味着模块内部代码紧密相关,功能单一,更容易重用。而耦合度则是模块间相互依赖的程度,低耦合度...

    Java代码可重用性的实现策略.pdf

    Java代码可重用性的实现策略有多种,包括接口编程、改写类的实例方法和代码分离等。这些方法可以帮助我们提高开发效率、简化代码和减少开发成本。但是,在实际应用中,我们需要根据实际情况选择合适的策略,避免代码...

    JAVA代码、方法、运算符大全

    本资源包"JAVA代码、方法、运算符大全"是针对Java初学者和进阶者的一份宝贵资料,它涵盖了Java编程中的核心元素:代码、方法和运算符。 一、Java代码 Java代码是实现特定功能的指令集合,它由类(Class)、方法...

    Java基础练习代码

    本文将深入探讨Java基础练习代码中的关键概念,帮助初学者巩固基础,提高编程技能。 首先,Java是一种面向对象的编程语言,它的核心特性包括封装、继承和多态。在练习代码中,你会看到如何定义类(class)并创建...

    Java代码规范2020.docx

    * 代码重用:尽量重用代码,避免重复编写相同的代码。 * 代码测试:编写单元测试,确保代码的正确性。 禁忌 在 Java 开发中,我们需要避免一些不良的编程习惯,以提高代码的质量和可维护性。 * 避免使用过长的...

    java简单实例程序源代码

    10. **ch6**: 可能讲解了多态性,这是面向对象编程的一个核心概念,允许父类引用指向子类对象,增强了代码的灵活性和重用性。 通过研究这些章节的源代码,学习者可以深入理解每个知识点的实际应用,并通过实践来...

    164个java完整代码

    7. **泛型**:泛型引入于Java 5,提高了代码的类型安全性和重用性,允许在类、接口和方法中使用类型参数。 8. **枚举**:Java的枚举类型提供了一种创建固定数量常量的优雅方式,比传统的final static变量更安全。 ...

    Java教材实例代码

    11. **泛型**:泛型引入了类型参数的概念,提高了代码的类型安全性和重用性。它可以用于类、接口和方法。 12. **注解(Annotation)**:注解为元数据提供了一种方式,可以在编译时或运行时被解析,用于简化配置、...

    可重用代码管理器

    总的来说,可重用代码管理器是现代软件开发中的重要辅助工具,它不仅提高了代码的复用性,降低了工作负担,还有助于保持代码库的整洁和一致性。对于团队协作而言,这样的工具更是不可或缺,因为它可以促进代码共享,...

    java代码质量控制

    Java代码质量控制是软件开发过程中不可或缺的一环,它关乎到代码的可读性、可维护性、性能以及潜在的bug预防。本篇将详细介绍几种常用的代码质量控制工具,包括它们的功能、用途以及如何使用。 首先,我们需要理解...

    java代码检测工具

    Java代码检测工具是一种用于提升代码质量和遵循编程规范的重要软件开发辅助工具。在Java开发过程中,保持代码的质量和一致性是至关重要的,因为这直接影响到软件的可靠性和可维护性。本压缩包提供了一款名为"PMD"的...

    java编程开源代码

    10. **泛型**:泛型引入了类型参数,提高了代码的类型安全性和重用性,避免了类型转换的麻烦。 11. **Lambda表达式**:Java 8引入的lambda表达式简化了函数式编程,使得编写简洁、可读性强的代码成为可能。 12. **...

    java编程艺术代码

    11. **泛型**:Java的泛型提供了一种在编译时进行类型检查的方法,增强了代码的安全性和重用性。代码示例将解释泛型类、接口和方法的使用。 12. **Lambda表达式**:自Java 8开始引入的lambda表达式简化了函数式编程...

    基于多源数据融合的Java代码知识图谱构建方法研究.pdf

    本文由哈尔滨工业大学计算机科学与技术学院的苏小红和王甜甜撰写,提出了一种基于多源数据融合的Java代码知识图谱构建方法,并对现有的API实体识别方法进行了实验和比较。 首先,知识图谱的概念于2012年被正式提出...

    java代码优化简介

    Java代码优化是对程序进行改进的过程,旨在提升程序的运行效率,减少资源的消耗。优化主要关注两个方面:减小代码体积和提高代码执行效率。在Java中,性能问题往往源于编程习惯而非语言本身。以下是一些针对Java代码...

Global site tag (gtag.js) - Google Analytics