从类、API、框架三个层面学习如何设计可复用软件实体的具体技术

一、复用级别

(1)代码的复用

包括目标代码和源代码的复用。其中目标代码的复用级别最低,历史也最久,当前大部分编程语言的运行支持系统都提供了连接(Link)、绑定(Binding)等功能来支持这种复用。源代码的复用级别略高于目标代码的复用,程序员在编程时把一些想复用的代码段复制到自己的程序中,但这样往往会产生一些新旧代码不匹配的错误。想大规模的实现源程序的复用只有依靠含有大量可复用构件的构件库。如”对象链接及嵌入”(OLE)技术,既支持在源程序级定义构件并用以构造新的系统,又使这些构件在目标代码的级别上仍然是一些独立的可复用构件,能够在运行时被灵活的得新组合为各种不同的应用。

(2)设计的复用

设计结果比源程序的抽象级别更高,因此它的复用受实现环境的影响较少,从而使可复用构件被复用的机会更多,并且所需的修改更少。这种复用有三种途径,第一种途径是从现有系统的设计结果中提取一些可复用的设计构件,并把这些构件应用于新系统的设计;第二种途径是把一个现有系统的全部设计文档在新的软硬件平台上重新实现,也就是把一个设计运用于多个具体的实现;第三种途径是独立于任何具体的应用,有计划地开发一些可复用的设计构件。

(3)分析的复用

这是比设计结果更高级别的复用,可复用的分析构件是针对问题域的某些事物或某些问题的抽象程度更高的解法,受设计技术及实现条件的影响很少,所以可复用的机会更大。复用的途径也有三种,即从现有系统的分析结果中提取可复用构件用于新系统的分析;用一份完整的分析文档作输入产生针对不同软硬件平台和其它实现条件的多项设计;独立于具体应用,专门开发一些可复用的分析构件。

(4)测试信息的复用

主要包括测试用例的复用和测试过程信息的复用。前者是把一个软件的测试用例在新的软件测试中使用,或者在软件作出修改时在新的一轮测试中使用。后者是在测试过程中通过软件工具自动地记录测试的过程信息,包括测试员的每一个操作、输入参数、测试用例及运行环境等一切信息。这种复用的级别,不便和分析、设计、编程的复用级别作准确的比较,因为被复用的不是同一事物的不同抽象层次,而是另一种信息,但从这些信息的形态看,大体处于与程序代码相当的级别。

二、可复用的类——LSP

1.在OOP之中设计可复用的类
2.封装和信息隐藏
3.继承和重写
4.多态、子类和重载
5.泛型编程
6.LSP原则
7.委派和组合(Composition)

(一)Liskov替换原则(LSP)
里氏替换原则的主要作用就是规范继承时子类的一些书写规则。其主要目的就是保持父类方法不被覆盖。

含义如下:

子类必须完全实现父类的方法
子类可以有自己的个性
覆盖或实现父类的方法时输入参数可以被放大
覆盖或实现父类的方法时输出结果可以被缩小
LSP是子类型关系的一个特殊定义,称为(强)行为子类型化。在编程语言中,LSP依赖于以下限制:

前置条件不能强化
后置条件不能弱化
不变量要保持或增强
子类型方法参数:逆变
子类型方法的返回值:协变
异常类型:协变

(二)委托
委派/委托:一个对象请求另一个对象的功能,是复用的一种常见形式。
委托可以被描述为在实体之间共享代码和数据的低级机制
委托依赖于动态绑定,因为它要求给定的方法调用可以在运行时调用不同的代码段。

委托和继承的比较:
    继承:通过新操作扩展基类或覆盖操作。
    委托:把基类拿过来作为新的类的元素,可以用基类以实现的功能扩展新类的功能
    委托可以替代继承的情况:如果子类只需要复用父类中的一小部分方法,可以不需
    要使用继承,而是通过委派机制来实现

(三)组合继承原则

类应该通过它们的组合实现多态行为和代码重用(通过包含实现所需功能的其他类的实例),而不是从基类或父类继承。

组合原则:
使用接口定义系统必须对外展示的不同侧面的行为,例如,一只鸟可以叫也可以飞,那么可以定义两个接口,quackable和flyable。
接口之间通过extends实现行为的扩展(接口组合)。然后可以定义一个接口birdable同时继承了上述两个接口,这样这个新的接口就有了上述两个接口的全部功能。
类implements 组合接口,从而规避了复杂的继承关系。接下来,我们定义的“鸟类”就可以实现birdable,使得活动顶层接口的功能(在构造实例的过程中,同时要delegation顶层功能的接口)

三、可复用的API和框架

之所以库和框架被称为系统层面的复用,是因为它们不仅定义了1个可复用的接口/类,而是将某个完整系统中的所有可复用的接口/类都实现出来,并且定义了这些类之间的交互关系、调用关系,从而形成了系统整体 的“架构”。

编写一个API需要考虑以下方面:

		API应该做一件事,且做得很好
		API应该尽可能小,但不能太小
		Implementation不应该影响API
		记录文档很重要
		考虑性能后果
		API必须与平台和平共存
		类的设计:尽量减少可变性,遵循LSP原则
		方法的设计:不要让客户做任何模块可以做的事情,及时报错

API

API是程序员最重要的资产和“荣耀”,吸引外部用户,提高声誉。

建议:始终以开发API的标准面对任何开发任务;面向“复用”编程而不是面向“应用”编程。
难度:要有足够良好的设计,一旦发布就无法再自由改变。 编写一个API需要考虑以下方面: API应该做一件事,且做得很好
API应该尽可能小,但不能太小 Implementation不应该影响API 记录文档很重要 考虑性能后果 API必须与平台和平共存
类的设计:尽量减少可变性,遵循LSP原则 方法的设计:不要让客户做任何模块可以做的事情,及时报错

框架

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。
前者是从应用方面而后者是从目的方面给出的定义。为了增加代码的复用性,可以使用委派和继承机制。同时,在使用这两种机制增加代码复用的过程中,我们也相应地在不同的类之间增加了关系(委派或继承关系)。而对于一个项目而言,各个不同类之间的依赖关系就可以看做为一个框架。一个大规模的项目可能由许多不同的框架组合而成。
框架与设计模式:
框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。构件通常是代码重用,而设计模式是设计重用,框架则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。

在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;
代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;
应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
框架与设计模式虽然相似,但却有着根本的不同。
设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
框架分为白盒框架和黑盒框架。

白盒框架:
框架分为白盒框架和黑盒框架。

白盒框架:
通过子类化和重写方法进行扩展(使用继承);
通用设计模式:模板方法;
子类具有主要方法但对框架进行控制。

黑盒框架:
通过实现插件接口进行扩展(使用组合/委派);
常用设计模式:Strategy, Observer ;
插件加载机制加载插件并对框架进行控制。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值