作者:夏彦端

看了mingjava在网站上的前三篇文章,觉得这本书确实值得大家认真的读,后来跟mingjava说想接着他的写,于是就有了这接下来的文章,希望不是狗尾续貂,写得不好,大家多多给我提意见,我会努力去改进的。

     由于以前学过C语言,所以对C还是蛮有感情,而JAVA和C又有很多相似之处,很多从C转过来学习JAVA的兄弟,可能一开始都不是很适应,因为很多在C里面的结构在JAVA里面都不能使用了,所以下面我们来介绍一下C语言结构的替代。

      Item 19:用类代替结构

      JAVA刚面世的时候,很多C程序员都认为用类来代替结构现在太复杂,代价太大了,但是实际上,如果一个JAVA的类退化到只包含一个数据域的话,这样的类与C语言的结构大致是等价的。

      比方说下面两个程序片段:

      class Point

      {

       private float x;

       private float y;

      }

      实际上这段代码和C语言的结构基本上没什么区别,但是这段代码恐怕是众多OO设计Fans所不齿的,因为它没有体现封装的优异性,没有体现面向对象设计的优点,当一个域被修改的时候,你不可能再采取任何辅助的措施了,那我们再来看一看采用包含私有域和共有访问方法的OO设计代码段:

      class Point

      {
       private float x;
       private float y;
       public Point(float x,float y)
       {
             this.x=x;
             this.y=y;
       }
        public float getX(){retrun x;}

        public float getY(){return y;}

        public void setX(float x){this.x=x;}

        public void setY(float y){this.y=y;}

      }

        单从表面上看,这段代码比上面那个多了很多行,还多了很多函数,但是仔细想一下,这样的OO设计,似乎更人性化,我们可以方面的对值域进行提取,修改等操作,而不直接和值域发生关系,这样的代码不仅让人容易读懂,而且很安全,还吸取了面向对象程序设计的灵活性,试想一下,如果一个共有类暴露它的值域,那么想要在将来的版本中进行修改是impossible的,因为共有类的客户代码已经遍布各处了。

需要提醒一点的是,如果一个类是包级私有的,或者是一个私有的嵌套类,则直接暴露其值域并无不妥之处。

 

Item 20:用类层次来代替联合

我们在用C语言来进行开发的时候,经常会用到联合这个概念,比如:

       typedef struct{

     double length;

     double width;    

}rectangleDimensions_t;

那我们在JAVA里面没有联合这个概念,那我们用什么呢?对!用继承,这也是JAVA最吸引我的地方之一,它可以使用更好的机制来定义耽搁数据类型,在Bruce Eckel的Thinking in java里面也多次提到了一个和形状有关的例子,我们可以先笼统的定义一个抽象类,即我们通常所指的超类,每个操作定义一个抽象的方法,其行为取决于标签的值,如果还有其他的操作不依赖于标签的值,则把操作变成根类(继承的类)中的具体方法。

这样做的最重要的优点是:类层次提供了类型的安全性。

其次代码非常明了,这也是OO设计的优点。

而且它很容易扩展,即使是面向多个方面的工作,能够同样胜任。

最后它可以反映这些类型之间本质上的层次关系,从而允许更强的灵活性,以便编译时类型检查。
 

Item 21:用类来代替enum结构

Java程序设计语言提出了类型安全枚举的模式来替代enum结构,它的基本思想很简单:定义一个类来代表枚举类型的单个元素,并且不提供任何公有的构造函数,相反,提供公有静态final类,使枚举类型中的每一个常量都对应一个域。

类型安全枚举类型的一个缺点是,装载枚举类的和构造常量对象时,需要一定的时间和空间开销,除非是在资源很受限制的设备比如蜂窝电哈和烤面包机上,否则在实际中这个问题不会被考虑。

 总之,类型安全枚举类型明显优于int类型,除非实在一个枚举类型主要被用做一个集合元素,或者主要用在一个资源非常不受限的环境下,否则类型安全枚举类型的缺点都不成问题,依次,在要求使用一个枚举类型的环境下,我们首先应考虑类型安全枚举类型模式。

 

Item 22:用类和接口来代替函数指针

众所周知,JAVA语言和C的最大区别在于,前者去掉了指针,小生第一次接触JAVA的时候觉得好不习惯,因为突然一下子没了指针,觉得好不方面啊,C语言的精髓在于其指针的运用,而JAVA却把它砍掉了,让人好生郁闷,不过随着时间的推移,我渐渐明白了用类和接口的应用也同样可以提供同样的功能,我们可以直接定义一个这样一个类,他的方法是执行其他方法上的操作,如果一个类仅仅是导出这样一个方法,那么它实际上就是一个指向该方法的指针,举个例子:

 class StringLengthComprator{

public int compare(String s1,String s2)

{

return s1.length()-s2.length();

}

}

这个类导出一个带两个字符串的方法,它是一个用于字符串比较的具体策略。它是无状态的,没有域,所以,这个类的所有实例在功能上都是等价的,可以节省不必要的对象创建开销。但是我们不好直接把这个类传递给可户使用,因为可户无法传递任何其他的比较策略。相反,我们可以定义一个接口,即我们在设计具体策略类的时候还需要定义一个策略接口:

      public interface Comparator{

           public int compare(Object o1,Object o2);

}

  我们完全可以依照自己的需要来定义它。

具体的策略类往往使用匿名类声明。

在JAVA中,我们为了实现指针的模式,声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类,如果一个具体策略只被使用一次的话,那么通常使用匿名类来声明和实例化这个具体策略类,如果一个策略类反复使用,那么它的类通常是一个私有的的静态成员类。