6. Abstract Data Type (ADT)


通过封装避免表示泄露。

1. ADT

1.1 Abstraction and User-Defined Types

抽象类型:强调“作用于数据上的操作”,程序员和用户无需关心数据如何具体存储,只需要设计/使用操作。

Bool类型的操作example

An abstract data type Bool has the following operations:

–true: Bool

–false: Bool

–and: Bool ×Bool → Bool

–or: Bool ×Bool → Bool

–not: Bool → Bool

但是有许多可能的方式去实现Bool,可以是bit(0/1),String(true/false),int(8/5 or >=0/<0)。

一个抽象数据类型是通过它的操作定义的,与内部如何实现无关

在这里插入图片描述

1.2 Classifying Types and Operations

Mutable:提供了可改变其内部数据的值的操作。

Immutable:其操作不改变内部值,而是构造新的对象

有些类型会提供两种形式,一种可变,一种不可变。StringBuilder(mutable) String(immutable)

Creators 构造器:create new objects of the type.

Producers 生产器:create new objects from old objects of the type.

Observers 观察器:take objects of the abstract type and return objects of a different type. ps:个人理解,用于观察对象的某些特征,需要其他类型来表示。

Mutators 变值器:change objects. immutable类型无变值器

在这里插入图片描述

1.2.1 signature of a creator

可能实现为构造函数或静态函数(工厂方法),String.valueof(Object obj)就是工厂方法的构造器。

1.2.2 signature of a mutator

变值器通常返回viod,如果返回值为void,则必然意味着它改变了对象的某些内部状态。也有其他返回值,比如boolean,或者对象本身。

在这里插入图片描述

1.3 Designing an Abstract Type

设计好的ADT,靠“经验法则”,提供一组操作,设计其行为规约的spec,不需要有具体的程序,根据程序的功能设计规约。

example:add方法并没有方法体

在这里插入图片描述

rule1:设计简洁、一致的操作。 rule2:要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度更低。

1.4 Testing ADT

测试creator,producters,and mutators:调用observers来观察这些操作的结果是否满足spec。

测试observers:调用creator,producters,and mutators等方法产生或改变对象,来看结果是否正确。

**风险:**如果被依赖的其他方法有错误,可能导致被测试方法的测试结果失效。

在这里插入图片描述

保证测试用例能够覆盖所有的部分

2. representation independence 表示独立性

表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。

除非ADT的操作指明了具体的pre-和post-condition,否则不能改变ADT的内部表示。

违反(violate)RI的例子:能够通过f直接访问属性,不可以!!!

在这里插入图片描述

保持RI的例子:

在这里插入图片描述

3. Invariants 不变量

final表示指向的地址不变,如果变量是mutable类型的,还是可能改变。

如果复制代价很高时,不得不将希望寄托于客户端,在规约中写明不可改变的值。否则,ADT有责任保证自己的不变量,并避免表示泄露。

summary:

  1. 不要将可变参数合并到对象中;使用防御型复制。

  2. 返回可变属性的防御性复制,或者返回可变属性的unmodifiable view 不可变视图。

  3. 使用不可变组件,消除防御性复制的需要。

如何建立不变量:
对象初始化和发生变化时,不变量都要为true。在return之前,要用checkRep()检查不变量是否保持。

三个标准来检查是否保持不变量:

  1. established by creators and producers;
  2. preserved by mutators, and observers;
  3. no representation exposure occurs

4. Rep Invariant and Abstraction Function

R(表示空间)和A(抽象空间)之间是满射、未必单射、未必双射。规约中的值只能使用A空间中的值,不能谈及任何内部表示细节,以及R空间中的值。所以AF和RI是注释形式,而不是java doc。

AF 抽象函数:R和A之间映射关系的函数,即如何去解释R中的每一个值为A中的每一个值。

RI 表示不变性:某个具体的“表示”是否是“合法的”。

例如:AF和RI都是对属性的描述与判断。

在这里插入图片描述

选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)——即如何映射

要精准记录RI(rep中所有的fields何为有效),和AF(如何解释每一个R值)。

设计ADT:选择R和A;RI–合法的表示值;AF–如何解释合法的表示值。

checkRep();用于监测RI是否满足。在所有可能改变rep的方法内(creators, producers, and mutators)都要检查。observer方法可以不用,但是建议也要检查。

5. Beneficent mutation 有益可变性 必考!

对immutable的ADT来说,它在A空间的abstract value应是不变的,但其内部表示的R空间中的取值则可以是变化的。这种变化叫做有益可变性。

在这里插入图片描述

observer方法mutate rep。这种mutator只是改变了R值,并未改变A值,对于client来说是immutable的---->AF并不是单射。

但是!并不代表immutable的类中可以随意出现mutator。

6. rep exposure 自证清白

在这里插入图片描述

mutable类型数据要制作防御性拷贝

7. ADT invariants replace preconditions ADT取代规约的前置条件

用ADT不变量取代复杂的 Precondition,相当于将复杂的precondition封装到了ADT内部。

example:

在这里插入图片描述

如果出错可以在编译阶段体现。通过名字SortedSet可以传达意思。更容易去改变,更改SortedSet后不需要改变exclusiveOr或者其他客户端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值