`
384444165
  • 浏览: 254662 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Effective Java读书笔记、感悟——3.类和接口(二)

 
阅读更多

一:接口优于抽象类

接口的优势:

现有的类很容易被更新,以实现新的接口。

接口是定义mixin(混合类型)的理想选择。

接口允许我们构造非层次接口的类型框架。

 

抽象类的作用和优势:

可以利用抽象类为每个接口定义一个骨架实现,其美妙之处在于它为抽象类提供了实现的帮助,但又不强加“抽象类被用作类型定义时”所特有的严格限制。

一般来说要在公有接口中增加方法,而不破坏实现这个接口的所有现有类是不可能的,二通过骨架实现类一定程度上通过默认实现减小带来的影响。因此接口一旦设计不可更改。

 

这里很好的例子是Mina的源码在IOAdapter部分的实现,可以看一下另一篇博客《深入阅读Mina源码(3) —— Mina之IOAdapter》中的图,有着清晰的骨架结构。

 

二:接口只用于定义类型

出于非用接口表明客户端可以如何使用类的动作的目的使用接口都是不恰当的。

常量接口模式是不良的使用习惯,虽然常量接口是Java中接口的一种形式出现,正确的做法应该是在工具类(前面有提到,不可实例化)定义,当大量用到工具类导出的常量的时候可以通过利用静态导入机制,避免用类名修饰常量名。(不推荐常量接口的原因是其导致把实现细节泄露到API中,对用户而言没有太大意义,而且当类需要修改不需要这个常量的时候还必须实现这个接口,保证二进制兼容性[你的改变不影响别人的改变],而且子类也收到污染。)

另外如果可以用枚举的话,枚举也是比较好的方式,Java的枚举是按照枚举类的方式实现的,通过实例化的不可实例化(就是在类内部实例化,构造函数为private)。虽然和OO的思想不太相符,但枚举比常量接口有更广的实用性和更好的性能,也许也是避免过多的被定义常量接口而产生的。

Java.io.ObjectStreamConstants是书中提到的反面教材,但其实也不是Java初衷吧,其目的是通过数据流、序列化和文件系统提供系统输入和输出,限定一些输入输出需要限定的值。这个接口从java1.1开始就引入,一旦发布就不能再去修改了,即便有了更好的方式,因此接口定义需要谨慎。

 

三:类层次优于标签类

这部分可以理解为多态的作用,避免将分类的标签信息存储在同一个类中。

 

四:用函数对象表示策略

函数指针的主要用途就是实现策略模式。在java中为了实现这种模式,要声明一个接口来表示该策略,并且为每个策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略类。当一个具体策略是设计用来重复使用的时候,它的类通常是要被实现为私有的静态成员类,并通过静态final域被导出,其类型为该策略接口。一个典型的例子是Comparator接口

 

五:优先考虑静态成员类

四种嵌套类:静态成员类、非静态成员类、匿名类、局部类

1.静态成员类与非静态成员类

非静态成员类的每个实例都隐含着与外围类的一个外围实例关联。如果嵌套类的实例可以在它的外围类的实例之外独立存在,这个嵌套类就必须是静态成员类:在没有外围实例的情况下,要想创建非静态成员类的实例是不可能的。非静态成员类在创建实例的时候都会建立不可修改的关联,消耗一定的实例空间。

非静态成员类的一种常见用法是定义Adapter,例如Set等实现自己迭代器。

如果声明成员类不要求访问外围实例,就要始终用static声明为静态成员类。

私有静态成员类常用于代表外围类所代表对象的组件。如Map的实现类内部的Entry,不然每个Entry都包含一个指向Map的引用,浪费很多的空间。

对共有、收保护的成员类一旦发布不能修改。

2.匿名类

不能有静态成员,且只有在非静态环境才有外部实例。

三种常见用法:动态创建函数对象;创建过程对象,如Runnable;静态工厂方法的内部。

3.四种嵌套类使用

à如果一个嵌套类需要在单个方法之外仍然可见,或者它太长了,不适合于放在方法内部,就应该使用成员类。

à如果成员类的每个实例都需要一个指向其外围实例的引用,就做成非静态,否则静态。

à假设这个类属于一个方法内部,如果你只需要在一个地方创建实例并已经有了一个预置的类型可以说明这个类的特征,就做成匿名类,否则局部类。两者都需要非常简短,不然影响到可读性。

 

2
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics