本节为课程重点。我们已经学习了数据与操作,将它们复合起来,构成ADT。
一、自定义的数据类型
二、对操作和数据进行分类
- 数据:可变和不可变
对于可变的对象,ADT内部会提供改变其值的操作。而不可变的类型的值不会改变,只会新建一个对象。
- 操作:构造器creator,生产器producer,观察器observer,变值器mutator
也就是说,构造器通常实现为一个构造函数或静态方法;生产器就是在对构造对象进行操作后,有一个新的对象产生,承接这个操作;观察器只是取走构造对象的一个属性,并不改变对象本身的属性;变值器则是改变了构造对象本身的一个可变类型的属性的值。
e.g.
三、设计ADT
设计要点:
1.设计简洁、一致的操作
2.要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度要低
例如list内部的get和size操作
3.要么抽象、要么具体,不要混合
四、表示独立性
五、测试ADT的方法
1.针对creator:构造对象之后,用observer去观察是否正确
2.针对observer:用其他三类方法构造对象,然后调用被测observer,判断观察结果是否正确
3.针对producer:produce新对象之后,用observer判断结果是否正确
六、保持不变量
需要尤其注意表示泄露的问题。因为既破坏了表示独立性,即让客户端接触到了本不应泄露的数据,同时也有破坏保持不变量的风险。
方法:防御式拷贝。返回的值是一个新定义的同类型数据,其值克隆原本的数据,但是可以保证数据不被泄露,不能更改。
当然,最好的方式是用immutable的类型,彻底避免表示泄露。
七、Rep Invariant and Abstraction Function
表示空间R:真实表现出的实体
抽象空间A:client看到和使用的值
Abstraction Function(AF):R和A之间映射关系的函数,即如何去解释R中的每一个值为A中的每一个值。
AF是一个未必单射,未必双射,但是满射的映射。也就是说,R中的部分值并非合法的,在A中无映射值