9 Construction for Reuse
面向复用的软件构造技术
复用类型
Types of Code Reuse
白盒复用:源代码可见,可修改和扩展;(继承)
白盒框架,通过代码层面的继承进行框架扩展;
黑盒复用:源代码不可见,不能修改,只能通过API接口来使用,简单清晰但适应性差;(委托)
黑盒框架,通过实现特定接口/delegation进行框架扩展
1.源代码级别的复用
2.模块级别的复用:类/抽象类/接口
例如:继承,委托(继承能做的事委托也能做,继承要求严格父子关系)
3.库级别的复用:API/包
4.系统级别的复用:框架
框架:一组具体类、抽象类、及其之间的连接关系;
只有“骨架”,没有“血肉”;
开发者根据framework的规约,填充自己的代码进去,形成完整系统(API和框架的区别:主控端在用户/框架)。
!!LSP
子类型多态:客户端可以用统一的方式处理不同类型的对象。
(任何引用父类型的情况,都可用子类型代替,通俗讲即父亲会的儿子一定要会)
LSP原则
能被Java静态类型检测检测出的:
1.子类型可以增加方法,但不可以删除方法
2.子类型需要实现抽象类型中的所有未实现的方法
3.子类型中重写的方法必须返回相同的类型或者子类型(满足协变)
4.子类型中重写的方法必须使用同样类型的参数(或符合逆变的参数)
5.子类型中重写的方法不能抛出额外的异常(协变)
方法要求:更强的不变量,更弱的前置条件,更强的后置条件。
协变:
父类型->子类型:越来越具体specific
返回值类型:不变或变得更具体
异常的类型:也是如此。
(数组支持协变)
逆变:
父类型->子类型:越来越具体specific
参数类型:要相反的变化,要不变或越来越抽象
JAVA不支持逆变,且识别其为重载。
泛型中的LSP
–
ArrayList
is a subtype of
List
–
List is not a subtype of
List