要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节。
设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰的隔离开来。然后,模块之间只通过它们的API进行通信,一个模块不需要
知道其他模块的内部工作情况。这被称为信息隐藏或者封装。
由于我们实现了很好的封装,只提供若干的API供客户端代码来访问,非API涉及的类和成员,客户端代码是无法直接使用的,这样我们在修改
这些非API涉及的类和成员,我们就不用担心客户端代码使用了它们,造成我们修改了这些代码,从而影响了客户端代码的行为。总之一句话,
合理的使用封装,为模块之间的松耦合而努力。
访问控制机制(access mode)决定了类,接口,成员的可访问性。正确的使用访问修饰符,对于实现信息隐藏是非常关键的。
第一条规则:尽可能使每个类和成员不被外界访问。尽可能使用最小的访问级别。
对于类和接口,只有两种可能的访问级别:包级私有的和公有的。使用public修饰符声明了类和接口,那么这个类和接口就是公有的;如果省略
public,那么这个类就是包级私有的。通过把类或者接口做成包级私有的,它实际上成了这个包的实现的一部分,而不是该包导出的API的一部分。
以后对它的修改,只需要担心这个包内的其他类对它的使用,而不用担心客户端代码对它的使用。特别,如果一个类只是在某一个类的类的内部
被使用到,那么我们可以考虑将这个类做成需要它的类的私有嵌套类(私有内部类),而不是包级私有类,这样就进一步降低了访问级别。
对于成员(五类:域,初始化块,构造器,方法,内部类、内部接口),有四种可能的访问级别:
私有的 private
包级私有的 缺省
受保护的 protected
公有的 public
应该把所有其他的成员都变成私有的,只有当同一个包中的另一个类真正需要访问一个成员时,才应该删除private修饰符,使该成员变成包级私有的。
从包级私有变成受保护的 ,会大大增强这个成员的可访问性。受保护的成员应该尽量少用。
实例域(非static的域)决不能是公有的。如果域是非final的,或者域是final的,但是引用的是一个可变对象,那么这个域一旦成为公有的,就放弃了
对存储在这个域中的值进行限制的能力。包含公有可变域的类并不是线程安全的。
对于静态域也建议尽量少使用公有的。但是一种情况除外,如果这个类提供了一些常量,那么可以通过公有的静态final域来暴露这些常量。通常,这些域
的名称由大写字母组成,单词之间下划线隔开。但是这些公有的静态final域,要么是基本类型的值,要么引用不可变对象的引用。如果final域指向的是可变
对象的引用,那么它就具有非final域的所有缺点,虽然引用本身不能被修改,但是它引用的对象却可以被修改-----这将导致灾难性的后果。