文章目录
模块级别的复用——继承和委托
前言
复习软件构造看到这里,PPT中对于类之间的关系中的association和composition的描述一摸一样,因此产生了疑问,查阅了相关的资料之后,弄明白了二者的区别,遂作此总结。
为什么要复用?
- 复用具有成本有效性和及时性。
- 可以通过缩短软件生产周期来提高软件生产效率,使用更少的资源和人力来开发软件。
- 不用耗费资源 “重复地造轮子”(reinvent-the-wheel)。
- 减少了维护成本,可以生产质量更高、更加可靠、效率更高的软件。
- 复用可以产生可靠的软件
- 重用已经存在一段时间并且经过调试的功能是构建稳定子系统的基础。
- 复用产生标准化的软件
- 重用GUI库可在应用程序中产生通用的外观。
- 与常规,连贯的设计保持一致。
两种模块复用的方式
Inheritance(继承)
这大概是最常用的关系了。子类通过extends关键字继承父类,从而获得父类的所有非私有的域和方法,比如Tiger类继承Animal类,它就具有了Animal的所有属性和行为。同时子类也可以重写(override) 或重定义(redefine) 父类的行为。通过继承的方法实现模块的复用,可以避免无用的通过调用或转发实现功能的方法,与实际情况更加吻合。但是子类继承了父类所有的域和方法,有时并非所有的父类行为都是我们需要的,这就产生了很多无用的方法,而且在使用继承之前通常都要设计好继承层级,这样也增加了实现的代价。
Delegation(委托)
委托相对于继承是一种更加灵活的模块复用方式。委托只是当一个对象依赖于另一个对象来实现其功能的某个子集时(一个实体将某些东西传递给另一个实体),例如 Sorter将功能委派给某些Comparator。明智的委派使代码重用成为可能,设计良好的委托有利于复用。可以分为显示委托(Explicit delegation,将发送对象传递给接收对象)和隐式委托(Implicit delegation,通过语言的成员查找规则)两种。
委托的三种类型
-
Use(使用)
使用类的最简单形式是调用其方法。两个类之间的这种关系形式称为“使用 - 关系”使用(其中一个类使用另一个类而不实际将其作为属性合并。例如,可以是参数或在方法中本地使用方法参数或者局部变量)。使用虚线箭头表示: -
Association(关联)
关联是更加紧密的一种重用形式,两个类中的任意一个都可以拥有对方作为自己的属性/实例变量,可以表示成英语中的“has a”关系。比如学生和老师就可以表示成这样的一种关联关系,一个老师可以有很多学生,而一个学生也可以有很多老师。使用标有数字的实线表示: -
Composition(组合)
这种复用形式是一种更加紧密的关系,其中一个类作为另一个类的组成部分并且不能脱离单独存在,可以表示成英语中的“owns a”关系。比如人和心脏的关系就可以表示成这样的组合关系,心脏作为人的一个组件,不能脱离人单独作为完整个体存在。使用实线和实心菱形来表示。
其他层次的复用
库级别的复用(Library/API)
库是一组提供可重用功能的类和方法(API)。一个好的API应该:易于学习、易于使用,即使没有文档、难以滥用、易于阅读和维护使用它的代码、足以满足要求的强大功能、易于发展、适合受众。
系统级别的复用(Framework)
系统级别的复用是通过Framework(框架) 来实现的。框架用于子系统设计,包含抽象和具体类的集合以及每个类之间的接口。通过添加组件来填充缺少的设计元素并实例化抽象类来实现子系统,是可重复使用的实体。应用框架是包含了接口、抽象类和具体类的可复用程序,使用时需要 在其基础上补充所需要的设计元素。扩展框架:需要扩展通用框架以创建特定的应用程序或子系统;框架可以延伸,开发者可以定义具体类从抽象类继承操作,增加能够被框架调用的方法;同时框架非常复杂,学习使用它们需要时间(例如DirectX或MFC)。