面向复用的软件

在开始学习的时候还是要有一个总的轮廓的,大体就是什么是可复用性,可复用性有啥特点,可复用性在哪些方面体现及其具体技术,剩下的就是一些细节了。

1.什么是复用

这里说的复用主要有两个方面的意思:

1.1面向复用编程

也就是说开发出可复用的软件

1.2基于复用编程

利用已有的可复用软件搭建应用系统

这些都很好理解,复用就是用已经有了的代码呗,一方面得使用,一方面还要写适合复用的代码

2.复用的特点

这里我们可以先思考一下,你能复用的东西它一定是存在一些共性的,才能再不同方面被重复使用,因此可复用的程序一定是与抽象程度高,共性强的程序相关联的。

2.1开发复用程序

特点:开发成本高,性能较差,适应性高。

2.2使用复用程序

特点:需要适配,代价可高可低,看适配程度

2.3总的来说

如果割裂开发与使用的话,没法得出客观的结论,但是如果放在一起考虑,我们就知道虽然前期进行复用程序的开发会导致开发成本高,时间多,但是随着开发的继续,可复用程序带来很多便利,比如标准化,高准确性,复用后时间成本降低等诸多特点,下面的图有很好的说明。

这里也可以看出如何衡量开发复用程序的好坏,那就是复用是否频繁,复用代价高低。这里可以简单的说,一个被频繁复用,且复用代价较低的程序,有较好的复用性。

3.四种复用级别

分别是代码(code),模块(class,interface),库(API,.jar),框架(framework)

这里也分两种复用

白盒复用:源代码可见,可修改和扩展,这个用得很多,比如你参考dl的代码进行修改,这就是白盒复用。

黑盒复用:源代码不可见,不能修改,只能使用某个API接口的功能。

3.1code reuse

这各方面大家用的最多就是复制别人的代码,然后简单修改一下来达到自己的功能。这是最低级的复用。

3.2module reuse

这里是重点,下面将介绍的是LSP原则,以及继承和委派来设计复用类

3.2.1LSP原则

1)子类型可以增加方法,但不可删

2)子类型需要实现抽象类型 (接口、抽象类)中所有未实现的方法

3)子类型中重写的方法必须有相同或子类型的返回值或者符合co-variant(协变)的参数

4)子类型中重写的方法必须使用同样类型的参数或者符合contra-variant(逆变)的参数(此种情况Java目前按照重载overload处理)

5)子类型中重写的方法不能抛出额外的异常(协变)

总结:更强的不变量,更弱的前置条件,更强的后置条件

3.2.2协变与逆变

协变:父类型到子类型,越来越具体的spec,返回值类型不变或者更具体,异常类型不变或者减少

逆变:父类型到子类型,越来越具体的spec,参数类型:不变或更抽象。

java不支持逆变,参数不用都看作是overload,想要重写必须是相同的参数类型

3.2.3泛型中的LSP

这里只需要知道结论,泛型不支持LSP也就是说List<Integer>不是List<Number>的子类,原因在于运行时类型擦除,提供为原始类型(父类或Object)

因此使用通配符解决泛型不协变的问题,例如下面这个例子:

 本意是要打印任意类型的List,但是由于泛型不协变,不同类型的List不存在父类子类的关系,因此需要使用通配符

 这样就可以打印出不同类型的List数组了

这里有特殊的通配符

(1)下限通配符

<? super A>  只能是A的父类或者A

(2)上线通配符

<? extends A> 只能是A(类或接口)的子类或者A

(3)多个限定(类或者接口)

要把类放在前面

3.2.4委派和组合(Delegation and Composition)

这里先给出一个比较的例子来看一下继承和委派的区别。

Comparator接口,用来构造一个比较器,然后用在sort函数中进行比较,使用的是委派

Comparable接口,类继承之后需要实现一个compareTo()的方法,然后override该方法,用在后面的比较,这里类似继承

这两种方法区别就是一个是在类的内部实现的,一个是在外部实现然后委派。

这里也能看出委派和继承的区别:稳定的复用使用继承,灵活的复用使用委派

3.2.4.1委派概念

一个对象请求另一个对象的功能,其实大家用的很多,不要被定义给吓到,就像是大家经常在代码中使用了一个List数组,这就是委派。

3.2.4.2继承和委派

很多设计模式将继承和委派结合使用。

如果子类只需要复用父类中的一部分方法,就是用委派。

如果子类与父类的关系很密切,方法使用很多,就用继承。

继承属于class层面的问题,是类的特点。而委派属于object层面的问题,是对象的特点。

有一个计算不同员工薪水的例子:

其思想就在于薪水的计算与对象密切相关,如果是继承的话重写的可能性极大,因此使用委派会更加灵活。 

上面的例子既有继承又有委派,我们称之为组合(composite)

组合优于继承,是委派的一种形式,实现基础就是子类型多态。在后面的设计模式中的策略模式就是借助这种组合的形式。在之后的设计模式中还会讲解,这里只需要知道此时的委派是下面种类中的Dependency临时性的委派,通过参数传递,使用后就消失

大致的设计方式:

 

3.2.4.3委派的种类

(1)Dependency(A use B)

只在方法的参数或者在方法的局部中使用发生联系,不表示,只使用,每次都要传参

(2)Association (A has B)

表示,可以构造,不可变化,反复使用

(3)Composition (A owns B)

表示时初始化或者唯一构造,客户端不可多种构造,不可变化,可反复使用

(4)Aggregation(更弱的association,可动态变化)

表示,可构造,可变化(set),反复使用

3.3Library reuse

3.3.1Library

一系列的类和方法(API)提供可复用的功能

就是开发者使用存在的库来进行开发,其中常见的就像JDKjava标准库

3.4System level

白盒框架:使用继承

黑盒框架:使用委派

白盒主要是继承框架然后重写方法,黑盒框架是把使用者的代码通过接口传给到框架。

4.总结

这里主要分享了一下什么复用,复用的特点,复用的4个层次。

其中着重说了LSP原则,以及继承与委派。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值