可复用性与设计模式

软件复用/重用

     为什么要复用/重用? 降低成本与开发时间,同时具有良好复用性的代码/软件是经过充分测试的,可靠且稳定。对于可复用的代码与软件,在不同标准下仍能保持一致。

     复用是完美的吗? 当然不是,这是显而易见的,当开发的应用仅仅需要面向某一个特定的对象时,此时采用复用,无疑增加了成本。(为什么在之前要说复用能够降低成本呢,这是考虑到复用的软件/代码被多次重复使用带来的结果,如下图所示)。 面向某一个特定对象时,显然针对性的进行开发,反倒能够降低成本。 并且有时复用的代码/软件在某些性能表现上,是不如针对性的软件/代码的。(可以想象某些算法可能针对某些问题具有良好表现,而针对另一些问题表现则不尽人意)

    

    那么是否应该进行复用呢?复用的机会有多频繁?复用的场合又有多少呢? 这里我想根据我Lab3开发的结果来看首先给出一个比较自我的结论:如果可以,请多采用复用,除非是指定完全针对某一对象。复用性设计对于多个项目的开发所带来的便捷与好处是显而易见的。  当然针对这个问题还是要具体情况具体分析

   那么如何进行复用呢? 首先是两种复用形式,白盒复用与黑盒复用。

   白盒复用:源代码可见,支持修改扩展。复制已有代码到系统中,可定制化程度高。例如本次实验Lab3中的location,resource等属性都属于这一范畴。

   黑盒复用:源代码不可见,只能通过API接口使用。常用的就是java包中的某些代码,比如list,set等,在我们使用的时候只是调用了它们的功能,而它们的代码实际上并没有看到。

    对于代码来说,最简单的复用自然是copy paste,这也是我们十分熟悉的一种复用方式。这种方式并不反对,但是对于我们求学者而言,还是要知其然并知其所以然是最好的。

   而更高一个层次的复用则来自类和接口。 类的复用在Lab3中接触实际上是十分多的。 大致分为两种:采用继承机制或者采用委托机制。 两者优缺点是非常明显的, 继承机制能够更好的应对维度并不多的项目,继承树逻辑清晰,维护代价低。 而委托机制则更加适用于具有多个维度的复杂项目,委托关系之间明确。 相对我个人而言是更加喜欢委托机制的,继承机制在多个维度的复用下,继承树是非常复杂的,逻辑关系并不明显,而且进行维护扩展时,不是那么方便。当然继承机制在复杂维度下也有一定好处,其给某些项目开发可复用的独特功能时,可以选择到某个属性层次的父类上进行开发,这样可复用性是比较强的。当然对于这两个方法的选择还是要依据项目而异。

   高一个层级的复用就是库/包/API等,在lab3时也编写了API,这类复用对于代码已然不可见,在客户端调用API等时,只需要关注是否实现功能即可,对于其内部实现显然并不那么重要(对于客户而言)

       复用的类型可变:实现可变:ADT有多种不同的实现,提供不同的representations和 abstract function,但具有同样的specification (pre-condition, postcondition, invariants),从而可以适应不同的应用场景。这与我们之前讲的ADT是一致的, 内部实现可能会经常变化,但客户端不应受到影响。

     设计可复用的类:子类型多态:客户端可用统一的方式处理 不同类型的对象 。例如我们想要使用List这个数据对象,我们可以将其实例化其子类ArrayList或其他List类型,对于List的基本操作对于其子类都是可以实现的,这就是子类型多态,如下图所示。:

   

 

      对于子类形编程有几个要求:1.子类型可以增加方法,但不可删   2.子类型需要实现抽象 类型 (接口、抽象类)中所有未实现的方法   3.子类型中重写的方法 必须有相同或子类型的返回值或者符合co-variant的参数    4.子类型中重写的 方法必须使用同样类型的参数或者符合contra-variant的参数(此种情况Java目 前按照重载overload处理)    5.子类型中重写的方法不能抛出额外的异常   对于子类型的spec也有如下规定:更强的不变量 更弱的前置条件 更强的后置条件

     对于协变和逆变,下图能够很好的解释:

     

     

    而有些时候会造成错误:

    

    CRP机制:CRP可以看作是继承和委托的结合。继承发生在接口层面,而委托发生在Object层面也就是类这一层面。本次Lab3的开发就选用的是CRP模式。开发者首先选取想要开发的项目的各个维度的属性,这些方法在接口上是委托给其他接口的。例如Entry接口中Location属性可以委托给Location接口。而在类里面Entry类中的Location也是委托给Locationimpl类实现的。

    

     CRP模式最大的好处在于,将复杂的继承树结构优化掉了。同时实现了接口之间的扩展(extends关键字)这样做复用性十分地高。

猜你喜欢

转载自www.cnblogs.com/fatdragon/p/12912677.html