软件构造 | Abstract Data Type (ADT)
软件构造 | Abstract Data Type (ADT)
抽象数据类型(ADT)是软件构造中的一个重要概念,它通过封装数据和操作来实现表示独立性,从而避免了表示泄露和潜在的bug。本文将详细介绍ADT的特性、不同类型的方法以及如何设计一个良好的ADT。
ADT的特性
ADT具有以下重要特性:
- 不变量(Invariant):确保数据结构在所有操作后都保持一致的状态。
- 表示泄漏(Representation Exposure):避免客户端获取数据的内部表示。
- 抽象函数(AF - Abstraction Function):定义表示值空间R到抽象值空间A的映射关系。
- 表示不变量(RI - Rep Invariant):定义哪些表示值是合法的。
通过这些特性,ADT能够在客户端和实现者之间建立一道“防火墙”,确保数据的正确性和安全性。
类型和操作分类
在面向对象编程中,类的方法通常可以分为以下四种类型:
构造器(Creators)
构造器用于创建新对象并初始化其状态。在Java中,构造器的主要作用是初始化类的新实例。构造器的特点是它们的方法名与类名相同,并且没有返回类型。当我们使用关键字new
来实例化一个类的对象时,实际上是在调用该类的构造器。
示例:
public class Person {
private String name;
// 构造器
public Person(String name) {
this.name = name;
}
// 其他方法
// ...
public static void main(String[] args) {
Person person1 = new Person("Alice"); // 调用构造器创建一个名为 Alice 的 Person 对象
}
}
生产器(Producers)
生产器是一种类型的方法,用于基于现有对象生成新的对象。生产器方法通常不会改变原始对象的状态,而是返回一个新对象,继承或衍生自原始对象。生产器方法可以帮助我们避免更改原始对象的状态或进行不必要的对象复制。
示例:
public class Circle {
private double radius;
// 生产器方法,返回一个新的 Circle 对象,半径为当前对象的两倍
public Circle createScaledCircle() {
return new Circle(this.radius * 2);
}
}
观察器(Observers)
观察器是一种类型的方法,用于查看对象的状态或属性,而不修改它们。观察器方法通常返回对象的状态或属性信息,而不会对对象进行任何更改。这有助于遵循对象的封装性原则,使对象的内部状态受到保护,并通过公共方法提供对状态的访问。
示例:
public class Rectangle {
private double width;
private double height;
// 观察器方法,返回矩形的面积
public double getArea() {
return this.width * this.height;
}
}
变值器(Mutators)
变值器是一种方法类型,用于改变对象的状态或属性值。变值器方法会修改对象所代表的数据,这可能会改变对象的内部状态。当我们需要更改对象的属性或状态时,可以使用变值器方法。
示例:
public class Car {
private String color;
// 变值器方法,用于设置汽车的颜色
public void setColor(String color) {
this.color = color;
}
}
以上是对Java中不同类型方法的详细解释,包括构造器、生产器、观察器和变值器。这些方法类型可以帮助我们更好地组织和理解类的功能,同时遵循良好的面向对象设计原则。
表示独立性
表示独立性是指客户端使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。这种设计原则可以确保ADT的实现细节对客户端透明,从而提高代码的可维护性和灵活性。
不同字符串表示的例子
设计ADT
设计ADT时需要考虑以下几点:
- 设计简洁、一致的操作
- 确保操作足以支持客户端对数据所做的所有操作需要
- 确保使用操作满足客户端需要的难度要低
- 要么针对抽象设计,要么针对具体应用的设计,不要混合
RI和AF
- R(Rep Value Space):表示值构成的空间,实现者看到和使用的值。
- A(Abstract Value Space):抽象值构成的空间,客户端看到和使用的值。
- ADT开发者关注表示空间R,客户端关注抽象空间A。ADT的内部表示(私有属性)对外部都应严格不可见。故在代码中以注释的形式写出AF和RI,防止被外部看到而破坏表示独立性/信息隐藏。
AF(Abstraction Function):R → A
- 抽象函数:R和A之间映射关系的函数,即如何将R中的每一个值解释为A中的每一个值。
- AF:满射、非单射、未必双射(R中的部分值并非合法的,在A中无映射值)。
RI(Rep Invariant):R → boolean
- RI可以看作:所有表示值的一个子集,包含了所有合法的表示值。
- RI也可看作:一个条件,描述了什么是“合法”的表示值。
设计ADT的步骤:
- 选择R和A
- 定义RI——合法的表示值
- 定义AF——如何解释合法的表示值
随时检查RI是否满足:在所有可能改变rep的方法内都要检查。