当类实现了某个接口时,我们就可以使用该接口类型来引用这个类实例,从而可以调用该类的方法来实现某些功能,除了这个目的之外,为了任何其他目的而定义接口是不恰当的,例如我们今天要谈到的常量接口。
一、什么是常量接口
这种只定义静态的final域, 每个域都是一个常量,而不定义任何方法的接口,被称为常量接口。例如以下代码:
//常量接口 - 不要使用!public interface MyConstants {static final double MY_NUMBER = 8.882;static final double MY_CONSTANT = 3.998;static final double MY_MASS = 27.998;}
二、为什么不应该使用常量接口
1、常量接口模式是对接口的不良使用
- 打破类的封装性
类本身要定义哪些常量,这应该是类的内部实现细节问题。如果实现常量接口会导致把这样的实现细节暴露到外界去。将会打破类的封装性,从而违反了面向对象原则。
- 可维护性差
如果在以后的版本中,这个类需要修改,需要删除这些常量,然而,由于暴露在外有可能被其他代码所使用,为了代码的兼容性, 它也必须保留这些常量,哪怕是散发着“腐败”的异味。
2、JDK的反面典型
在JDK的类库中也曾经定义了几个常量接口,比如java.io.ObjectStreamConstants。这些接口是JDK1.2版本时发布的,那时候还没有这么多设计模式和原则的约束,后期为了代码的兼容性不得不保留下来,可以说是反面的典型,应该引以为戒。
三、如何定义常量
1、定义到相关的类中
如果这些常量与某个类紧密相关,就应该把这些常量添加到这个类中,并把可见性设置为Private。
2、使用枚举
如果这些常量适合用枚举类型来表达,就应该毫不犹豫地使用枚举类型。
3、使用工具类
使用不可实例化的常量工具类来定义常量,例如以下代码:
//静态常量工具类public class MyConstants {private MyConstants() { } //不可实例化public static final double MY_NUMBER = 8.882;public static final double MY_CONSTANT = 3.998;public static final double MY_MASS = 27.998;}
如果大量利用工具类来定义常量, 可以通过利用静态导入(static import)机制,避免用类名来修饰常量名。
简而言之,接口应该只被用来定义类型, 它们不应该被用来定义常量。