本文主要总结可复用性的概念以及面向可复用性的软件构造技术。
可复用性简介
可复用性通俗的来讲就是我们写好的代码模块可不可以被重复使用,编程过程中使用可复用的模块可以大大减少我们编程的时间,代码更标准,实现更可靠。
两种复用的方式:白盒复用和黑盒复用。黑盒复用就类似于调用API接口,或者方法等等;白盒复用是直接得到想要复用的源代码(或其他内容)等等,然后自己根据需要进行修改。
根据复用内容的结构从小到大,分为如下四种复用。
(1).源代码级别的复用:这个是最底层的复用,就是简单的复制粘贴修改。
(2).模块级复用:以class作为最基本的单元,复用的方式有继承和委托,其中委托的耦合度明显低于继承。
(3).类库级重用:相当于把一系列的class进行了打包,类似于第三方库的调用。
(4).框架级复用:在框架的基础上,填充自己的代码,形成完整系统。
面向复用的软件构造技术
Liskov Substitution Principle 里氏替换原则(LSP)
LSP原理涉及的编译强制规则如下:
子类型可以增加方法,但不可删除方法
子类型需要实现抽象类型中的所有未实现方法
协变:子类型中重写的方法必须有相同或子类型的返回值或者符合co-variance的参数
逆变:子类型中重写的方法必须使用同样类型的参数或者符合contra-variance的参数
子类型中重写的方法不能抛出额外的异常
Also applies to specified behavior (methods):
Same or stronger invariants 更强的不变量
Same or weaker preconditions 更弱的前置条件
Same or stronger postconditions 更强的后置条件
委托与组合
委托顾名思义,类似于现实中我们委托别人去做一些事情,抽象到代码中,那就是在某个类的方法中,传入其他类的变量,把实现逻辑写在这个其他类的方法中,并在这个类的方法中调用。
例如我们想通过List的复用性实现stack,如果是继承关系的话,则stack中不可避免的有很多与我们期待的数据结构不匹配的方法。因此我们应该采取委托的方式,将pop等函数里某些操作委托给list即可。
由于继承过于严格,因此如果不是有很强的继承关系,使用委托会更合适。
总的来说,委托有四种形式。
(1).依赖(Dependency):逻辑即为A use B,在A的方法中通过把B当作参数来或在方法的局部中,调用B的方法,是一种临时性的委托,只有调用这个方法的时候,它们才有临时关系。
(2).关联(Association):逻辑即为A has B,对象A中的字段中有对象B,之后的操作和前面类似;只是A与B之间就有一个相对长的关系了。
(3).组合(Composition):逻辑即为B is part of B,A中有字段B,且在A被构造时,B就被初始化好了(A中的定义导致的,比如A中有private T B = new T(…)语句);因此它们声明周期一致。
(4).聚合(Aggregation):逻辑即为A owns B,与(3)很相似,只是B构造的方式是通过A的构造函数的参数。因此对于B的构造,比第三种要灵活。