复用的几种类型
- 源代码级别的复用
- 模块级别的复用(类,抽象类,接口)
- 库级别的复用(API,包)
- 系统级别的复用(框架)
软件复用的定义
- 复用的成本(图示)
- 开发成本更高(足够高的适应性),但缺乏针对性
评估可复用性
- 复用的机会有多少?复用的场合有多少?
- 复用的代价?
软件复用的形态和层面
-
最主要在于代码层面,但是所有实体均可以。
-
复用的类型
-白盒复用:源代码可见,可以修改扩展(复制代码到正在开发的系统)
-黑盒复用:源代码不可见,无法修改(只可通过API接口来使用) -
源代码级别的复用
-直接复制代码(最低级别的复用)
模块级别的复用 - 类和接口
- 类是代码复用的原子单元,优缺点如图所示
- 类复用的方式----继承(相关的问题)
- 类复用的方式:委托
-Delegation is simply when one object relies on another object for some subset of its functionality
-两种委托的方法:
库级别的复用(API和包)
- 库的定义:类和方法(API)的集合,提供可复用函数
- 框架的定义:可复用的骨架代码,可以被自定义为应用程序
- 两者的区别如图所示
系统级别的复用–框架
- 一组具体类、抽象类、及其之间的连接关系
- 开发者根据
framework的规约,填充自己的代码进去,形成完整系统 - 分类:黑盒框架通过实现特定接口/delegation进行
框架扩展,白盒框架通过代码层面的继承进行框架扩展
设计可复用类
- 主线
Behavioral subtyping and Liskov Substitution Principle (LSP)
- 子类型多态:客户端可用统一的方式处理不同类型的对象
eg:
**编译器强制的几点要求(动态类型检查) - 子类型可以增加方法,但不可删
- 子类型需要实现抽象类型 (接口、抽象类)中所有未实现的方法
- 子类型中重写的方法必须有相同或子类型的返回值或者符合co-variant的参数
- 子类型中重写的方法必须使用同样类型的参数或者符合contra-variant的参数(此种情况Java目
前按照重载overload处理) - 子类型中重写的方法不能抛出额外的异常
-
ex1:相同和增加的不变量;重写的方法具有相同的前置条件和后置条
件
ex2:相同和增加的不变量;重写的方法具有更弱的前置条件(能够接受更多);更强的后置条件。
反例如图所示:
无法比较规约的强度大小!
- 强行为子类型化
- 协变:父类型→子类型:越来越具体specific;返回值类型:不变或变得更具体
- 对于异常类型也是如此的规则,为子类型的方法声明的每个异常都应该是为超类型的方法声明的某个异常的子类型
- 反协变,逆变
父类型→子类型:越来越具体specific参数类型:要相反的变化,要不变或越来越抽象
- 但是,在java中这种情况被当作重载
- 总结如下: