本章阐述的一些原则,将使你设计出更加有用、健壮和灵活的类和接口。
第十三条:使类和成员的
可访问性最小化
区别设计的模块是否良好,关键在于这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节。设计良好的模块会把自己的API和具体实现隔离开,只通过API和外部通信,这个概念成为信息隐藏或封装。
之所以信息隐藏这么重要,是基于这样一个事实:它可以有效解除各模块之间的耦合关系,使得这些模块可以独立开发、测试、优化、使用、理解和修改。这样可以加快开发速度,实现并行开发。
Java提供了许多机制来协助信息隐藏。访问控制决定了类、接口和成员的可访问性。正确使用访问修饰符格外关键。
总之,尽可能降低可访问性,防止把任何散乱的类、接口和成员变成API的一部分。除了公有静态final域的特殊情形,公有类不应该包含公有域,并且确保公有静态final域所引用的对象都是不可变的。
第十四条:在公有类中
使用访问方法而非公有域
如果类可以再它所在的包的外部进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。如果公有类暴露了它的数据域,要想在将来改变其内部是不可能的,客户端代码早就遍布各处。
然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误。虽然客户端代码与该类的内部表示法紧密相连,但是这些代码被限定在包中。
第十五条:使可变性最小化
不可变类只是其实例不能被修改的类。它们比可变的类更易于设计、实现和使用。
为了使类变成不可变类,要遵循下面原则:
1.不要提供任何会修改对象状态的方法;
2.保证类不会被扩展。为了防止子类化,一般做法是使这个类成为final的
3.使所有的域都是final
4.使所有的域都成为私有的。虽然从技术上讲,允许不可变的类具有公有的final域,但不建议这样,除非确定以后不会再有任何修改。
5.确保对于任何可变组件的互斥访问。
不可变类具有很多优点,是目前流行的函数式编程思想的重要组成部分,也是新兴的clojure,scala等语言的亮点。这里不做过多介绍。
第十六条:复合优先于继承
继承是实现代码重用的有力手段,但它绝非是永远完成这项工作的最佳工具。比如,对普通的具体类进行跨越包边界的继承,是非常危险的。
与方法调用不同,继承打破了封装性。子类依赖于超类中特定功能的实现。并且,子类必须要跟着超类的更新而演变。
如果超类获得了一个新的方法,但你给子类提供了一个签名相同返回类型不同的方法,那么子类将无法通过编译。如果给子类提供的方法和超类具有相同的签名和返回类型,实际上就覆盖了超类的方法。
有一种方法可以避免这些问题。不用扩展现有的类,而是在新的类中添加一个私有域,它引用现有类的一个实例。这种设计被称作“复合”。因为现有的类变成了新类的一个组件。新类中的每个实例方法都可以调用被包含的现有类的方法,并返回结果。这被称作转发,新类中的方法被称作转发方法。
简而言之,只有当子类和超类之间存在子类型关系时,使用继承才是恰当的。即便如此,如果子类和超类处于不同的包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性。为了避免,可以使用复合和转发机制来代替继承,尤其是在存在适当的接口可以实现包装类的时候,包装类不仅比子类更加健壮,而且功能更强大。
第十七条:要么为继承而设计并提供文档说明,要么就禁止继承
为了允许继承,类必须遵守一些约束。构造器决不能调用可被覆盖的方法。
如果你决定在一个为了继承而设计的类中实现Cloneable或者Serializable接口,就应该意识到,因为clone和readObject方法在行为上类似于构造器,所以不能调用可覆盖的方法。此外,如果继承了Serializable,该类中的readResolve或writeReplace方法必须成为受保护的方法,而不是私有方法。
第十八条:接口优于抽象类
因为java只允许单继承,所以,抽象类作为类型定义受到了很大的限制。任何一个类,只要遵守约定,就被允许实现一个接口。
1.现有的类可以很容易被更新,以实现新的接口。
2.接口是定义mixin(混合类型)的理想选择。
3.接口允许我们构造非层次结构的类型框架。
虽然接口极为灵活的,但接口一旦被公开,并被实现,再想改变几乎是不可能的。所以必须在初次设计的时候就保证接口正确。
第十九条:接口只用于定义类型
当类实现接口时,接口就充当这个类的实例的类型。
有一种接口叫做常量接口,它不包含任何方法,只有静态的final域,每个域都导出一个常量。但是这种模式是对接口的不良使用。
如果要导出常量,有几种合理的方法。如果这些常量与某个现有的类或接口紧密相关,就应该把这些常量添加到这个类或接口中。或者编写一个不可实例化的工具类。
总之,接口用来只定义类型,不应该被用来导出常量。
第二十条:类层次优于标签类
第二十一条:用函数对象表示策略
有些语言支持函数指针的主要用途就是实现策略模式(比如比较器函数)。为了在Java中实现这种模式,要声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略类。当一个具体策略是设计用来重复使用的时候,它的类通常就要被实现为私有的静态成员类,并通过公有的静态final域被导出,其类型为该策略接口。
第二十二条:优先考虑静态成员类
嵌套类是指被定义在另一个类的内部的类。嵌套类存在的目的是为外围类提供服务。嵌套类有四种:静态成员类、非静态成员类、匿名类和局部类。除了第一种,其他三种都称为内部类。
静态成员类和非静态成员类语法相似,前者包含static修饰符。但非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。如果声明成员类不要求返回外围实例,就要选择静态成员类,节省空间和时间。
分享到:
相关推荐
在C#编程语言中,类、接口、虚方法和抽象方法是面向对象设计的重要组成部分。这里我们将详细讨论这些概念以及抽象类与接口之间的相同点和区别。 首先,让我们来看看抽象类(Abstract Class): 1. 抽象方法是只有...
### 详细解析Java中抽象类和接口的区别 #### 引言 在面向对象编程中,Java作为一种广泛应用的编程语言,提供了多种方式来实现抽象的概念。其中最常用的两种机制是抽象类(abstract class)和接口(interface)。这...
本项目主要包括项目开发环境搭建、不同功能的类的设计、抽象类的设计、接口的设计、及其继承抽象类重写和接口实现类等具体功能的实现。 ●工程项目搭建与游戏初始化功能实现(2学时) ; ●动物城成员列表与动物信息...
Java中的类、抽象类和接口的区别和联系
### 抽象类和接口的区别分析 在面向对象编程中,抽象类与接口都是实现代码复用和提高软件模块化的重要工具。它们各自拥有独特的特性和应用场景,掌握这些概念对于编写高质量、可维护性强的代码至关重要。下面我们将...
在C#编程语言中,抽象类和接口是实现面向对象编程(OOP)中的多态性和代码重用的关键概念。本文将深入探讨这两个概念,并解释它们在C#中的使用方式和区别。 ### 抽象类 抽象类是一种特殊的类,它不能被实例化,其...
抽象类和接口实验报告
在编程世界中,抽象类和接口是面向对象设计的重要概念,它们都用于实现代码的抽象和多态性,但有着不同的使用场景和规则。这里我们将深入探讨这两种机制,并结合给出的"codePiece"代码片段来分析它们在实际应用中的...
在C#编程语言中,抽象类和接口都是用于实现面向对象编程中多态特性的关键概念。它们都旨在为其他类提供一种定义行为和特性的模板或规范,但它们之间存在着重要的区别。本文将详细探讨C#中的抽象类与接口之间的差异,...
在编程世界中,抽象类和接口是两种非常重要的概念,它们在实现代码的组织和设计模式上发挥着关键作用。本文将深入探讨抽象类与接口的异同,并结合实际应用场景来帮助理解这两种机制。 首先,让我们从定义开始。抽象...
简单介绍了抽象类和接口
本次实验主要聚焦于Java编程语言中抽象类和接口的概念理解与实际运用,旨在深入掌握抽象类与抽象方法的定义,以及接口的定义与实现方法。通过具体实例,如形状类的创建与扩展,电话类的层次构建,以及教师类的排序...
### 抽象类和接口的详细区别和联系 在面向对象编程中,抽象类与接口是两种非常重要的概念,它们都是实现多态性的方式之一,但在使用场景、语法特性和设计哲学等方面存在明显的不同。本篇文章将深入探讨这两者的区别...
在Java编程语言中,抽象类和接口是两个核心的概念,它们在实现多态性和组织类结构方面起着重要作用。抽象类和接口虽然在某些方面看似相似,但它们在用法和含义上有着明显的区别。 首先,抽象类是一种特殊的类,它...
在面向对象编程中,抽象类和接口是两种非常重要的概念,它们在软件设计和实现过程中发挥着不可替代的作用。本文将深入探讨这两种概念的区别,帮助开发者更好地理解和运用它们。 #### 一、定义 1. **抽象类**:抽象...
在Java语言中,abstract class和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,...
Java中的抽象类(abstract class)和接口(interface)都是用于创建抽象化模型的重要工具,它们在面向对象编程中扮演着核心角色。这两种机制都允许我们定义一组方法的签名,但不提供具体实现,从而实现“设计契约”...
"抽象类和接口的区别" 抽象类和接口是 Java 语言中两种不同的机制,用于实现对象的抽象描述。虽然它们之间存在着一定的相似性,但它们在定义、实现和使用方面存在着很大的区别。 首先,抽象类是一个抽象的概念,...