目录
1 Abstraction and User Defined Types
2 Classifying Types and Operations
6 Testing an Abstract Data Type
8 Rep Invariant and Abstraction Function
10 Documenting the AF, RI, andSafety from Rep Exposure
1 Abstraction and User Defined Types
数据抽象:由一组操作所刻画的数据类型
传统的类型定义:关注数据的具体表示
抽象类型:强调“作用于数据上的操作”,程序员和client 无需关心数据如何具体存储的,只需设计 使用操作即可。
2 Classifying Types and Operations
1.可变和不可变类型
可变类型:提供了可改变其内部数据的值的操作,例如Date
不可变类型:其操作不可改变内部值,而是构造新的对象,例如String
2.抽象数据型的操作
构造器:对与这个类型,从无到有创建一个新的对象。可能实现为构造函数或静态
函数。实现为静态方法的 构造器 通常称为工厂方法。
A creator may take an object as an argument, but not an object of the type
being constructed.
生产器:从一个对象,产生一个新的对象。
The concat method of String , for example, is a producer: it takes two
strings and produces a new one representing their concatenation.
观察器:返回对象的一些特征。
Observers take objects of the abstract type and return objects of a
different type.
变值器:改变对象属性的方法,变值器通常返回void,也有可能返回boolean
The add() method of List , for example, mutates a list by adding an
element to the end.
3 Abstract Data Type Examples
1.int
int is immutable, so it has no mutators.
creators: the numeric literals 0 , 1 , 2 , …
producers: arithmetic operators + , --, * ,
observers: comparison operators == , != , < ,
mutators: none (it’s immutable)
2.String
creators: String constructors
producers: concat , substring , toUpperCase
observers: length , charAt
mutators: none
3.List
List is also an interface, which means that other classes provide the actual implementation of the
data type, such as ArrayList and LinkedList
creators: ArrayList and LinkedList constructors,Collections.singletonList
producers:Collections.unmodifiableList
observers: size , get
mutators: add , remove , addAll , Collections.sort
4 Designing an Abstract Type
原则1:设计简洁、一致的操作
原则2:要足以支持 client 对数据所做的所有操作需要,且用操作满足 client 需要的难度要低
5 Representation Independence
表示独立性: client 使用 ADT 时无需考虑其内部如何实现, ADT 内部表示的变化不应影响外部 spec 和客户端。通过前提条件和后置条件充分 刻画了 ADT 的操作 spec 规定了 client 和 implementer 之间的契约,明确了 client 知道 可以 依赖哪些内容, implementer 知道可以安全更改的内容。
6 Testing an Abstract Data Type
测试 creators, producers, and mutators :调用 observers 来观察这些operations 的结果是否满足 spec
测试 observers :调用 creators, producers, and mutators 等方法产生或改变对象,来看结果是否正确。
7 Invariants
不变量:程序在任何时候总是true 的性质,由 ADT来负责其不变量,与 client 端的任何行为无关。
方法:使用private和final修饰变量
使用immutable类型
防御式拷贝
8 Rep Invariant and Abstraction Function
两个空间:
R表示值构成的空间:实现者看到和使用的值
A抽象值构成的空间: client 看到和使用的值
ADT 开发者关注表示空间 R client 关注抽象空间 A
映射关系R→A
满射:抽象空间的数据必须在表示空间中全部实现。
未必单射:表示空间的数据未必全部出现在抽象空间
未必双射
表示不变性 RI :某个具体的“表示”是否是“合法的
选择某种特定的表示方式 R ,进而指定某个子集是“合法”的 ( RI),并为该子集中的每个值做出“解释 ”( 即如何映射到抽象空间中的值。
同样的表示空间 R ,可以有不同 RI。即使是同样的 R 、同样的 RI ,也可能有不同的 AF ,即“解释不同”。
设计ADT :
(1) 选择 R 和 A ;
(2) RI 合法的表示值;
(3) 如何解释合法的表示值 映射 AF。做出具体的解释:每个rep value 如何映射到 abstract value
使用checkRep ()方法检查不变量
9 Beneficent mutation
对 immutable 的 ADT 来说,它在 A 空间的 abstract value 应是不变的。 但其内部表示的 R 空间中的取值则可以是变化的。这种 mutation 只是改变了 R 值,并未改变 A 值,对 client 来说是
immutable 的 AF 并非单射”,从一个 R 值变成了另一个 R 值。 此种可变是无害的,甚至是有益的。
10 Documenting the AF, RI, andSafety from Rep Exposure
在代码中用注释形式记录 AF 和 RI
要精确的记录 RI rep 中的所有 fields 何为有效
要精确记录 AF :如何解释每一个 R 值
规约:ADT 的规约里只能使用 client 可见的内容来撰写,包括参数、返回值、异常等。
如果规约里需要提及“值”,只能使用 A 空间中的“值”。
ADT 的规约里也不应谈及任何内部表示的细节,以及 R 空间中的任何值
ADT 的内部表示 私有属性 对外部都应严格不可见,故在代码中以注释的形式写出 AF 和 RI 而不
能在 Javadoc 文档中,防止被外部看到而破坏表示独立性 信息隐藏