ADT的基本操作
Creator(构造器)、Producer(生产器)、Observer(观察器)、Mutator(变值器)
-
构造器
可将对象作为参数
一种方法,负责成员变量的初始化
可能实现为构造函数或静态函数
举例:Constructor、静态(工厂)方法 -
生产器
从已有的对象中生成新的对象 -
观察器
获得对象内部的某种特性 -
变值器
改变对象某些内部状态的方法
通常返回void,也可能返回非空类型
举例如下:
操作的测试:
用Observer 观察Creator、Producer、Mutator的方法是否正确
用Creator、Producer、Mutator产生或改变数据,测试Observer是否正确
好的ADT需要具备的性质
表示独立性(Representation Independence)
ADT的使用与其内部表示无关
内部表示的改变对代码没有影响
可以完成对程序内容的优化但不影响使用者的代码
表示不变量(Representation Invariant)
不变量是一种属性,它在程序运行的时候总是一种状态
ADT要能够确定内部的不变量恒定不变,不受外部影响
保持不变量可以简化对代码的分析,对使用到它的部分直接跳过即可;若可变,则需要对每一处使用到该变量的地方都进行分析和审查
抽象函数(Abstract Function)
表示域:值具体的实现实体
抽象域:类型设计时支持使用的值,由表示域抽象而来,也是使用者关注的重点
表示域和抽象域的关系:
- 每一个抽象值都是由表示值映射而来
- 一些抽象值是被多个表示值映射而来的
- 不是所有的表示值都能映射到抽象域中
抽象函数:
表示值到其抽象值的映射 AF:R→A
能够清晰地表示一个输入到一个输出是怎么对应的
示意图如下:
表示不变量(RI)和抽象函数(AF)在程序中的描述举例:
无表示泄露(Safety from Rep Exposure)
表示泄露:外部代码可以直接修改内部存储的数据
主要有如下几种可能:
- 数据的类型为public,可以从外部直接访问、修改
- 返回的对象是可变(mutable)类型的,虽然前有private final修饰,但变量的值仍可从外部修改
- 对ADT中的可变类型对象,多次使用同一个对象赋值,内存中始终指向同一个区域,该对象被不断地修改
内存泄露的解决方法(针对常见情况):
1. 不要使用public类型,而改用private final修饰
2. 在返回可变类型对象时,使用防御性拷贝,新建一个该类型对象返回
public Date getTimestamp() {
return new Date(timestamp.getTime());
}
3. 在创建内部的可变类型对象时,也要使用防御式编程
public Tweet(String author, String text, Date timestamp) {
this.author = author;
this.text = text;
this.timestamp = new Date(timestamp.getTime());
}
4. 万不得已时还可以使用spec限定的方法