5.2 Construction for Reuse面向复用的软件构造技术

5.2 Construction for Reuse面向复用的软件构造技术

 

 

1.设计可复用的类

--继承与重写

--重载

--参数多态和泛型编程

--行为子类型和Liskov替换原则

--组合与委托

2.设计可复用库和框架

--API和库

--Framework    JAVA Collections framework

 

 

1 Designing reusable classes 设计可复用的类

(1) Behavioral subtyping and Liskov Substitution Principle (LSP)

子类型多态和Liskov替换原则

 

子类型多态:客户端可用统一的方式处理不同类型的对象

 

子类型多态

Liskov Substitution Principle(LSP)

JAVA中的强制规则:

--子类型可以增加方法但是不可删

--子类型需要实现抽象类型中的所有未实现方法

--子类型中重写的方法必须有相同或子类型的返回值或者符合co-variance的参数

--子类型中重写的方法必须使用同样类型的参数或者符合contravariance的参数

--子类型重写的方法不能抛出额外的异常

 

方法中的行为:

更强的不变量;

更弱的前置条件;

更强的后置条件

 

Ex1: for Behavioral subtyping (LSP)

子类满足相同的不变量原则

重写方法前置和后置田间一样

 

Ex2:(LSP)

满足相同的不变量原则

重写方法的前置条件更弱 后置条件更强

 

 

LSP是一种子类关系的定义,叫做强行为子类化(strong) behavioral subtyping

LSP依赖于下列的限制:

前置条件不能强化;

后置条件不能弱化;

不变量要保持;

子类型方法参数协变(co-variance)

子类型返回值协变

异常类型协变

体现在:

 

父类型到子类型:越来越具体 specific

返回值类型:不变或变得更具体

异常的类型:也是如此。

 

Cotravariance(反协变,逆变)

父类型到子类型:越来越具体的spec

参数类型:相反变化,要不变或越来越抽象

 

JAVA中把这种情况当作overload看待

 

 

数组是协变的

 

 

 

 

List<String> 不是List<Object>的子类

 

不能让List<Number>指向List<Integer>

但是可以往List<Number>中加入Long等类型

 

 

泛型不是协变

类型擦除:把所有的泛型用具体类型代替

 

 

 

不确定的通配类型用通配符表示如List<?>

下列情况利用通配符:

1. 所写的方法可以用Object实现 2.不需要利用具体的类型

3 方法不依赖于T

 

通配符类似泛型,与List<Object>不同的是,List<?>是List<Integer>的子类

List<? super Integer> 是 List<Integer>的父类

 List<? extends Number>是List<Number> 的子类

 

 

 

 

(2) Delegation and Composition 委托和组成

 

Comparator<T>接口

实现int compare(T o1,T o2)方法,按顺序比较两个参数

三种利用:

1. Comparator可以放在具体的方法中,进行排序。

如:Collections.sort(int[] List,Comparator cmp)或者Arrays.sort

2. 放在具体的结构中控制数据顺序,如Set和Map

3. 实现集合类不按照自然顺序排

 

 

 

另一种方法Comparable<T>接口

让你的 ADT 实现 Comparable 接口,然后 override compareTo() 方法

 

与使用 Comparator 的区别:不需要构建新的 Comparator 类,比较代

码放在 ADT 内部

这不再是委托了

 

 

Delegation:

委派/委托:一个对象请求另一个对象的功能

委派是复用的一种常见形式

委派模式:通过运行时动态绑定,实现对其他类中代码的动态复用

 

 

 

 

如果子类只需要复用父类中的一小部分方法

可以不需要使用继承,而是通过委派机制来实现

一个类不需要继承另一个类的全部方法,通过委托机制调用部分方法,从而避免大量无用的方法

 

委托发生在 object 层面,而“继承”发生在 class 层面

 

使用接口定义系统必须对外展示的不同侧面的行为

接口之间通过 extends 实现行为的扩展(接口组合)

类 implements 组合接口从而规避了复杂的继承关系

 

接口定义行为

(1) Dependency: 临时性的 delegation

往方法里传入接口类,调用具体方法后随栈弹出

 

(2) Association: 永久性的 delegation

类中定义属性

 

(2) Composition: 更强的 association ,但难以变化

在类中初始化方法,但初始化后难以改变

 

 

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

 

先不初始化

 

 

 

 

 

 

 

 

 

2* Designing system-level reusable libraries and frameworks

猜你喜欢

转载自blog.csdn.net/qq_42766619/article/details/91382166
5.2
今日推荐