软件构造复习——面向复用的软件构造技术(PPT9)

在这里插入图片描述
在这里插入图片描述


一、可重用组件的级别和形态

在这里插入图片描述
在这里插入图片描述
白盒复用(继承):源代码可见,可修改和扩展
黑盒复用 (委托):源代码不可见,不能修改

在这里插入图片描述
模块级的重用:类/接口

在这里插入图片描述
在这里插入图片描述

类是代码重用的原子单元
– 不需要源代码,类文件或 jar/zip
– 只需要包含在类路径中
– 可以使用 javap 工具获取类的公共方法头
§ 文档非常重要(Java API)
§ 封装有助于重用
§ 更少的代码来管理
§ 版本控制,向后兼容性仍然存在问题
§ 需要将相关类打包在一起——静态链接

在这里插入图片描述

在这里插入图片描述

二、设计可重用的类

在这里插入图片描述

在 OOP 中设计可重用的类
§ 封装和信息隐藏
§ 继承和覆盖
§ 多态、子类型和重载
§ 通用编程
§ 行为子类型和 Liskov 替换原则 (LSP)
§ 委托与组成

2.1 LSP原则

在这里插入图片描述
在这里插入图片描述

子类实现相同的不变量(以及其他不变量)
重写的方法具有相同的前置条件和后置条件

在这里插入图片描述
子类的RI要么不变,要么变强

在这里插入图片描述
在这里插入图片描述
LSP 是子类型关系的特殊定义,称为(强)行为子类型
在编程语言中,LSP 依赖于以下内容
限制:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
协变:返回值类型、异常在子类中更加具体
反协变(目前会被认为是overload):传入的参数值向上(父类型)抽象

在这里插入图片描述

在这里插入图片描述

数组是协变的:给定 Java 的子类型规则,类型 T[] 的数组可以包含类型 T 或 T 的任何子类型的元素。
§ 在运行时,Java 知道这个数组实际上被实例化为一个整数数组,它恰好可以通过 Number[] 类型的引用访问

在这里插入图片描述

那么,在泛型中呢?泛型不是协变的
§ 泛型是类型不变的
– ArrayList 是 List 的子类型
– List 不是 List 的子类型

§ 类型参数的类型信息在代码编译完成后被编译器丢弃; 因此该类型信息在运行时不可用。
§ 这个过程叫做类型擦除
§ 泛型不是协变的

在这里插入图片描述

类型擦除:如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或对象。 因此,生成的字节码仅包含普通的类、接口和方法

在这里插入图片描述

我们不能将整数列表视为数字列表的子类型。
这对于类型系统来说是不安全的,编译器会立即拒绝它

Box 不是 Box 的子类型,即使 Integer 是 Number 的子类型。
给定两个具体类型 A 和 B(例如,数字和整数),无论 A 和 B 是否相关,MyClass 与 MyClass 都没有关系。 MyClass 和 MyClass 的共同父对象是 Object。

有关当类型参数相关时如何在两个泛型类之间创建类似子类型的关系的信息,请参阅通配符

在这里插入图片描述

无界通配符类型使用通配符 (?) 指定,例如 List<?>。
– 这称为未知类型的列表。
§ 在两种情况下,无界通配符是一种有用的方法:
– 如果您正在编写可以使用 Object 类中提供的功能实现的方法。
– 当代码使用不依赖于类型参数的泛型类中的方法时。 例如,List.size 或 List.clear。
– 实际上,Class<?> 之所以如此常用,是因为 ClassT 中的大多数方法都不依赖于 T

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述printList 的目标是打印任何类型的列表,但未能实现该目标
— 它只打印一个 Object 实例列表; 它不能打印 List、List、List 等,因为它们不是 List 的子类型。
要编写通用的 printList 方法,请使用 List<?>

在这里插入图片描述
上界通配符<?super A> A和A的父类
下界通配符<?extends A>A和A的子类

在这里插入图片描述
在这里插入图片描述

2.2委托和composition

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有关comparable和comparator的区别,在CSDN上有许多优秀的文章可以进行参考
区别1
区别2
区别3
区别4

在这里插入图片描述

委托只是当一个对象依赖另一个对象来实现其功能的某些子集时(一个实体将某些东西传递给另一个实体)
委托可以被描述为一种低级的共享机制
实体之间的代码和数据。
– 显式委托:将发送对象传递给接收对象
– 隐式委托:通过语言的成员查找规则

在这里插入图片描述
在这里插入图片描述

假设我们想要一个将其操作记录到控制台的列表…
– LoggingList 由一个列表组成,并将(非日志)功能委托给该列表。

在这里插入图片描述

继承:通过新操作或覆盖操作扩展基类。
§ 委托:捕获一个操作并将其发送给另一个对象。
§ 许多设计模式结合使用继承和委托。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
employ是一个普通,普通类里用接口做为一个成员变量,manger继承了employee类,调用了(实现父类接口)的实现类里的(具体方法)

动物ADT例子

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
要好好理解上面这个图!!!
要好好理解上面这个图!!!
要好好理解上面这个图!!!
在这里插入图片描述
在这里插入图片描述

使用类的最简单形式是调用它的方法;
§ 两个类之间的这种关系形式称为“uses-a”关系,其中一个类使用另一个类,但实际上并未将其合并为一个属性。 - 例如,它可以是参数或在方法中本地使用。
§ 依赖:一个对象需要其他对象(供应商)来实现的临时关系

在这里插入图片描述

关联:对象类之间的持久关系,它允许一个对象实例导致另一个代表它执行操作。
– has_a:一个类有另一个作为属性/实例变量
– 这种关系是结构性的,因为它指定一种对象与另一种对象相连,并不代表行为

在这里插入图片描述
组合是一种将简单的对象或数据类型组合成更复杂的对象或数据类型的方法。
– is_part_of:一个类有另一个作为属性/实例变量
– 实现为一个对象包含另一个对象。

在这里插入图片描述
聚合:对象存在于另一个之外,在外部创建,因此它作为参数传递给构造函数

在这里插入图片描述

三、设计系统级可重用 API 库和框架

在这里插入图片描述

白盒框架
– 通过子类化和覆盖方法进行扩展
– 常见设计模式:模板方法
– 子类有主要方法,但将控制权交给框架

黑盒框架
– 通过实现插件接口进行扩展
– 常见设计模式:策略、观察者
– 插件加载机制加载插件并控制框架

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

白盒测试:通过子类化和覆盖方法进行扩展子类具有主要方法,但将控制权交给框架

在这里插入图片描述
在这里插入图片描述

黑盒测试:通过实现插件接口扩展插件加载机制加载插件并控制框架
在这里插入图片描述
感觉白盒测试主要使用override对代码里面进行重写,黑盒框架是用接口印出来,接触不到里面的代码东西。

总结:
在这里插入图片描述

白盒框架使用子类化/子类型化—继承
– 允许扩展每个非私有方法
– 需要理解超类的实现
– 一次只能扩展一个
– 一起编译
– 通常是所谓的开发者框架
黑盒框架使用组合——委派/组合
– 允许扩展界面中公开的功能
– 只需要了解界面
– 多个插件
– 通常提供更多的模块化
– 可以单独部署(.jar、.dll、…)
– 通常是所谓的最终用户框架、平台

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_50906780/article/details/118404944
今日推荐