程序设计技术之开闭原则(OCP)

电子说

1.2w人已加入

描述

周立功教授数年之心血之作《程序设计与数据结构》以及《面向AMetal框架与接口的编程(上)》,书本内容公开后,在电子行业掀起一片学习热潮。经周立功教授授权,本公众号特对《程序设计与数据结构》一书内容进行连载,愿共勉之。

第二章为程序设计技术,本文为2.4.3 开闭原则(OCP)

>>> 2.4.3 开闭原则(OCP)

开闭原则(Open-Closed Princple,OCP)就是敏捷软件开发的基本原则之一,一个模块应该“对扩展开放,而对修改关闭。”比如,一个USB端口可以扩展,但不需要做任何修改就可以接受一个新的设备,因此,对于USB应用设备来说,一台有USB端口的计算机是扩展开放而对修改关闭的。当设计遵循OCP原则时,它可以通过增加新的代码来进行扩展,而不是修改已有的代码。比如,即使某个模块的内部实现改变了,但对外的接口也不能变,其目的是隔离变化。OCP通常要求我们对软件进行抽象,因为只有具有共性的抽象的接口,才会有具体的实现的可能性。接口放在哪里呢?应该放在用户端,而不是实现的一方。

假设只允许将0~9之内的value值push到栈中,即min=0,max=9。根据OCP原则,需要编写一个调用push()功能的函数pushWithRangeCheck()。将其共性——范围值的合法性判断包含在函数体内,而可变的value值、min和max通过形参应对。其函数原型为:

开闭原则

如果value值非法,则返回false;如果value值合法,则调用push()。此时,如果栈不满,则返回true,否则返回false,详见程序清单 2.36。

程序清单 2.36 范围值校验器范例程序(1)

开闭原则

由此可见,如果正确地应用OCP,那么以后再进行同样的改动时,则只需要添加新的代码,而不必改动已经正常运行的代码。如果仅需1-2种校验器,则上述方法非常简单明了。当需要组合多种校验器一起使用时,则上述方法传递的参数太多,而且每次push时,都要传递允许的范围参数。如果将min和max分离出来成为一个Range类型结构体,即可避免以上问题:

开闭原则

根据OCP开闭原则,需要再编写一个扩展push功能的pushWithRangeCheck(),范围值校验器范例程序详见程序清单 2.37。

程序清单 2.37范围值校验器范例程序(2)

开闭原则

如果再添加一个奇偶校验器,则需要判断push到栈中的数据是否为偶数,创建与之相应的OddEven类型结构体如下:

开闭原则

根据OCP开闭原则,还需要再编写一个扩展push功能的pushWithOddEvenCheck()。即:

开闭原则

为了避免用户直接操作成员,则需要定义相应的校验接口函数。即:

开闭原则

由于范围值校验函数和偶数校验函数都有一个指向当前对象的指针,因此可以将特殊的Range *pRange和OddEven *pOddEven泛化为void *pData。即:

开闭原则

无论是范围值校验还是偶数校验,其共性是对输入参数进行校验,因此可以共用一个函数指针。其函数原型如下:

开闭原则

为了便于阅读,如程序清单 2.38所示展示了通用校验器的接口。

程序清单 2.38 通用校验器的接口(validator.h)

开闭原则

尽管无法预知将要支持什么校验器,但调用者知道,因此可以将范围值校验器和奇偶校验器功能分离出来成为单独的函数,编写一个通用的pushWithValidate()函数,通过函数指针调用相应的校验函数,且不用在意具体校验器内部的实现,使用validator.h接口的通用校验器范例程序详见程序清单 2.39。

程序清单 2.39通用校验器范例程序

开闭原则

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分