可复用的软件:
- 开发成本 高于一般软件的成本:要有足够高的适应性
- 性能差些: 针对普适场景,因此面对具体场景缺少足够的针对性
最主要的复用是在代码层面,但软件构造过程中的任何实体都可能被复用
- 需求
- 设计/规约spec
- 数据
- 测试用例
- 文档
对于code层面的reuse,有两种模式:
- 白盒复用:源代码可见,可修改和扩展
- 复制已有代码到正在开发的系统,进行修改
- 可定制化程度高
- 对 其修改增加了软件的复杂度,且需要对其内部充分的了解
- 黑盒复用:源代码不可见,不能修改
- 只能通过API接口来使用,无法修改代码
- 简单,清晰
- 适应性差些
Source code reuse
需要复制相应代码片段到自己的系统中,需要对源代码内部有一定了解,需要根据自己的系统修改,过程中出错的风险很高
Module-level reuse: class/interface
通过继承或委派的方式灵活复用
Library-level reuse: API/Package
库:一组提供可重用功能的类和方法(api)
框架:可重用的骨架代码,可以定制到应用程序中
System-level reuse: Framework
框架:一组具体类、抽象类、及其之间的连接关系
- 只有“骨架”,没有“血肉”
开发者根据 framework的规约,填充自己的代码进去,形成完整系统
Framework作为主 程序加以执行,执 行过程中调用开发者所写的程序
开发者根据 Framework预留的 接口所写的程序
框架是针对一系列问题给出的解决方案,有两种框架:
- 白盒框架,通过代码层面的继承进行框架扩展
- 现有的功能通过子类化框架基类和重写预定义的钩子方法来扩展
- 通常使用模板方法模式等设计模式来覆盖钩子方法。
- 黑盒框架,通过实现特定接口/delegation进行 框架扩展
- 通过定义符合特定接口的组件来重用现有功能
- 这些组件通过委托与框架集成
设计可复用类
- 封装和信息隐藏
- 继承和重写
- 多态性、子类型和重载
- 泛型编程
Behavioral subtyping and Liskov Substitution Principle (LSP)
子类型多态:客户端可用统一的方式处理 不同类型的对象
关于LSP原则:
- 子类型可以增加方法,但不可删
- 子类型需要实现抽象 类型中的所有未实现方法
- 子类型中重写的方法 必须有相同类型的返回值或者符合co-variance的返回值
- 子类型中重写的 方法必须使用同样类型的参数或者符合contra-variance的参数
- 子类型中重写的方 法不能抛出额外的异常,抛出相同或者符合co-variance的异常
- 更强的不变量
- 更弱的前置条件
- 更强的后置条件
关于通配符
- List<? super Interger>可以使用Integer以及其父类
- List<? extends A>
Delegation and Composition
如果你的ADT需要比较大小,或者要放入Collections或Arrays进行 排序,可实现Comparator接口并override compare()函数。
另一种方法:让你的ADT实现Comparable接口,然后override compareTo() 方法,与使用Comparator的区别:不需要构建新的Comparator类,比较代 码放在ADT内部。 ▪ This is not delegation any longer.
委派/委托:一个对象请求另一个对象的功能,委派是复用的一种常见形式
委派模式:通过运行时动态绑定,实现对 其他类中代码的动态复用
委派模式:通过运行时动态绑定,实现对 其他类中代码的动态复用,从而避免大量无用的方法
“委托” 发生在object层面,而“继承”发生在class层面
Composite Reuse Principle (CRP)原则更倾向于使用委派而不是继承来实现复用。
对于委派,分为:
-
Dependency临时性的委派
- Delegation关系通过方法的参数传递建立起来
-
Association永久性的委派
- Delegation关系通过固有的field建立起来,这个field根据传入参数修改
-
Composition更强的委派
- Composition是Association的一种特殊类型,其中Delegation关系通过类内 部field初始化建立起来,无法修改
-
Aggregation更弱的association,可动态变化
- Aggregation也是Association的一种特殊类型,其中Delegation关系通过客 户端调用构造函数或专门方法建立起来
- 这种委派其实就是,在Association的基础上,增加了set方法,能把association设置的委派参数再通过传入新的参数修改
-
Use (A use one or multiple B)
-
Association (A has one or multiple B)
-
Composition/aggregation (A owns one or multiple B)