面向可复用设计的软件构造
作者:互联网
可复用性的度量、形态与外部表现
源代码级别的复用、模块级别的复用:类/抽象类/接口、库级别的复用:API/包、系统级别的复用:框架
代码复用
代码级别:方法等
模块级别:类和接口
库级别:API
系统级别:框架
代码级别
白盒复用:源代码可见,可修改和扩展。复制已有代码当正在开发的系统,进行修改。可定制化程度高,对其修改增加了软件的复杂度,且需要对其内部充分的了解。
黑盒复用:源代码不可见,不能修改。只能通过API接口来使用,无法修改代码。简单,清晰,但适应性差。
模块级别
继承和接口
库级别
易学、方便使用
系统级别
框架:一组具体类、抽象类、及其之间的连接关系。开发者根据framework的规约,填充自己的代码进去,形成完整系统。将framework看作是更大规模的API复用,除了提供可复用的API,还将这些模块之间的关系都确定下来,形成了整体应用的领域复用
额外的复用
类型可变
泛型:适应不同的类型,且满足LSP(5-2)
实现可变
ADT可以通过多种实现方式。虽然有不同的表示(Rep)和抽象函数(AF)但是却有相同的前置条件、后置条件和不变性。从而可以适应不同的应用场景。
表示不变性,虽然内部的实现可能会经常发生变化,但是客户端不受影响。(表示独立,信息隐藏)
面向复用的软件构造技术
设计可复用的类
继承与重写、重载、参数多态与泛型编程、行为子类型与Liskov替换原则(LSP) 、组合与委派
设计可复用的库和框架
设计可复用的类
行为子类型与Liskov替换原则(LSP)
子类型多态:客户端可用统一的方式处理不同类型的对象
子类型的行为:
1.子类型可以增加方法,但不可删
2.子类型需要实现抽象类型中的所有未实现方法
3.子类型中重写的方法必须有相同或子类型的返回值或者符合的参数
4.子类型中重写的方法不能抛出额外的异常
对于不变量来说:
相同或者是更强的不变量、相同或者更弱的前置条件、相同或者更强的后置条件
Covariance (协变)和Contravariance (逆变)
协变:父类型到子类型,更具体的规约。返回值和异常的类型要么保持不变要么变得更加具体。
逆变:父类型到子类型,更具体的规约。但是参数类型变得更加宽泛了。
在有容器套用的情况下,首先要求容器必须子类和父类的关系,再比较容器内部所储存的类型若相同则是子类和父类的关系。
设计系统级别的库和框架
之所以library和framework被称为系统层面的复用,是因为它们不仅定义了1个可复用的接口/类,而是将某个完整系统中的所有可复用的接口/类都实现出来。并且定义了这些类之间的交互关系、调用关系,从而形成了系统整体的“架构”。
API设计
框架设计
Java集合框架
面向复用的设计模式
设计模式更多的强调的是多个类/对象之间的关系和交互过程。
结构模式
Adapter(适配器模式)Decorator(装饰器模式)Facade(外观模式)
行为模式
Strategy(策略模式)Template(模板模式)Iterator(迭代器模式)
适配器模式
将某个类/接口转换为client期望的其他形式。通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体子类。
装饰器模式
用每个子类实现不同的特性,但是在对这个子类进行处理的时候,可能会出现多种共有的但是额外的特性。若果再单独建立子类的话会导致代码量特别巨大。所以
装饰器模式:对每一个特性构造子类,通过委派机制增加到对象上。
当客户端需要多种特性时,可以通过层层装饰来实现。
外观模式
客户端需要通过一个简化的接口来访问复杂系统内的功能,提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用。可以理解成在外观模式定义的方法中,提供必要的参数然后将调用操作封装在其内部进行。
策略模式
有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里。
具体操作是,建立总策略接口,在里面声明方法,对于不同具体策略重写方法,达到不同策略的要求。
模板模式
做事情的步骤一样,但具体方法不同。共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现 。
使用继承和重写实现模板模式,具体关系如图
迭代器模式
客户端希望遍历被放入容器/集合类的一组ADT对象,无需关心容器的具体类型 。也就是说,不管对象被放进哪里,都应该提供同样的遍历方式。
迭代器的三个需要重写的方法:hasNext, next, remove
并且需要在ADT中重写提供迭代对象的方法。
标签:子类,复用,接口,面向,类型,软件,模式,级别 来源: https://www.cnblogs.com/Gusimo22/p/16373323.html