软构:抽象数据类型 (ADT)

抽象数据类型 (ADT)

目  录

第1 抽象类型和用户定义的类型

第2 对类型和操作进行分类

第3 抽象数据类型示例

第4 抽象类型设计

第5 Git作为软件配置管理工具的一个示例

第6 测试抽象数据类型

第7 不变量

8节 表示不变性和抽象函数

9节 有益的可变性

10节 记录AF、RI、以及表示泄露的安全性

  1. 抽象类型和用户定义的类型
  1. 抽象类型:

强调“作用于数据上的操作”,程序员和client无需关心数据如何具体存储的,只需设计/使用操作即可。ADT是由操作定义的,与其内部如何实现无关!

(2)用户定义:除了编程语言所提供的基本数据类型和对象数据类型,程序员可定义自己的数据类型。

  1. 对类型和操作进行分类
  1. 可变类型:提供了一些操作,执行这些操作会导致同一对象上的其他操作的结果产生不同的结果。
  2. 不可变类型:其操作不改变内部值,而是构造新的对象。
  3. 抽象类型的操作:

Creators:构造器,创建该类型的新对象,创建者可以将对象作为参数,但不能将其作为正在构造的类型的对象。可能实现为构造函数或静态函数(工厂方法)

Producers:生产器,从该类型的旧对象中创建新对象。

Observers:观察器,获取抽象类型的对象,并返回不同类型的对象。

Mutators:变值器,改变对象属性的方法,通常返回void,或返回boolean等非空类型

  1. 抽象数据类型示例

  1. 抽象类型设计
  1. 少而精的操作,目的明确,行为连贯
  2. 要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度要低
  3. 要么抽象、要么具体,不要混合 --- 要么针对抽象设计,要么针对具体应用的设计。
  1. 表示独立性
  1. Representation Independence表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。除非ADT的操作指明了具体的pre-和post-condition,否则不能改变ADT的内部表示——spec规定了client和implementer之间的契约。
  1. 测试抽象数据类型
  1. 如何测试ADT:为ADT的每个操作创建测试。

测试creators, producers, and mutators:调用observers来观察这些operations的结果是否满足spec;

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

  1. 不变量
  1. 保持不变量invariants:不变性是一个关键的不变量:一旦创建,不可变对象应该在其整个生命周期中始终代表相同的值。由ADT来负责其不变量,与client端的任何行为无关。
  2. 为什么要保持不变量:保持程序的“正确性”,容易发现错误,总是要假设client有“恶意”破坏ADT的不变量---defensive programming(有意或无意)
  3. 表示泄露rep exposure: 不仅影响不变性,也影响了表示独立性:无法在不影响客户端的情况下改变其内部表示。
  4. 使用private和public关键字表示哪些字段和方法只能在类内访问,哪些可以从类外部访问。final关键字还可以确保在构造对象后不会重新分配此不可变类型的字段。
  5. 防御性复制Defensive copying:我们可以通过使用防御性复制来修复这种表示泄漏:制作一个可变对象的副本,以避免泄漏对表示方法的引用。复制可变对象的另一种方法是clone(),某些类型支持,但不是全部支持。
  6. 最好的办法就是使用immutable的类型,彻底避免表示泄露。

  1. 表示不变性和抽象函数

R:表示空间,表示值(代表值)的空间由实际实现实体的值组成

A:抽象值构成的空间:client看到和使用的值

ADT开发者关注表示空间R,client关注抽象空间A

  1. Rep Invariant表示不变性:

RI告诉我们空间R中的r是否被AF映射到了空间A中的某个值,RI形成了空间R的一个子集(子集中的所有元素均被AF映射到了空间A中)

  1. Abstraction Function抽象函数:

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

  1. 相同的R可能有不同的RI,即使是同样的R、同样的RI,也可能有不同的AF,即“解释不同”。
  2. RI和AF设计ADT

设计ADT:(1) 选择R和A;(2) RI --- 合法的表示值;(3) 如何解释合法的表示值 ---映射AF

  1. 检查RI

  1. 有益的可变性
  1. 抽象值永远不应该改变,对immutable的ADT来说,它在A空间的abstract value应是不变的。
  2. 有益的可变性:实现方法是可以自由更改表示值的,只要它继续映射到相同的抽象值,那么客户端就不知道这种更改,但其内部表示的R空间中的取值则可以是变化的。
  3. 这种mutation只是改变了R值,并未改变A值,对client来说是immutable的 à“AF并非单射”,从一个R值变成了另一个R值
  1. 记录AF、RI、以及表示泄露的安全性
  1. 在代码中用注释形式记录AF和RI,要精确的记录RI:rep中的所有fields何为有效要精确记录AF:如何解释每一个R 值。
  2. rep exposure safety argument表示泄漏的安全声明:给出理由,证明代码并未对外泄露其内部表示——自证清白

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值