温小宁
摘 要:本文从面向对象程序的分析设计入手,简要分析了面向对象程序的设计方法,借助C++语言提出了面向对象程序设计的若干思维方式,对面向对象程序设计的一体化教学实践开展了一些实践探索和思考。
关键词:面向对象;分析设计;思维方法
中图分类号:G712 文献标识码:A 文章编号:1005-1422(2015)05-0065-02
面向对象的系统分析设计,就是将面向对象的方法运用到解决实际问题中去,完成对某个特定领用领域的分析和建模的过程。要解决系统的对象、对象的属性和操作、对象的动态特性、对象间的构造关系及通信关系等。系统设计阶段最重要的任务是确定系统结构,包括将系统划分成若干个子系统,确定子系统的本质特征,拟定数据管理策略、协调子系统软硬件和全局性资源分配,决定软件控制的实现方法、系统的边界条件和交替使用优先权等。在设计阶段,要通过建立一些类以及它们之间的关系来解决问题,要求设计语言必须具有抽象、封装、继承和多态性等关键性要素。C++语言不是一种纯面向对象的语言,但C++语言的可靠性、可重用性、可扩充性和良好的可维护性使它在面向对象程序设计中具有得天独厚的优越性。笔者在多年的程序设计教学中,结合学生实际,实施一体化教学,取得了一些初步成效。
一、巧用设计方法,解决程序的“先天缺陷”
1.单一设计方法的局限性
设计是程序的基础和前提,关乎系统的全局性,如果设计出了问题,对整个体系的影响将是灾难性的。传统的自顶向下的设计方法,从问题大的方面入手来寻找解决办法,依次类推逐步深入,再用同样的方法来解决剩下的相对较小的问题。运用自顶向下设计方法掌握结构层次的关键技术是恰当地、有选择地忽略某些细节方面的问题,集中精力“找主干、搭框架”。其精髓是把难度大的问题被分解成一系列难度小的技术问题,先解决大问题,然后再依次解决小问题。但是,实际运作过程中往往并无规律可循,什么是大问题,什么是小问题,哪些问题应先解决,哪些问题可以后解决,往往很难界定,因问题有时很难表述清楚。一旦划分有误,又要折返,重新排查,陷入麻烦。这对设计者的前瞻性和敏锐的洞察力具有很高的要求。
与之相对,自底向上的设计方法是从解决基本的、简单的问题入手,在此基础上逐步建立解决复杂问题的机制,直到整个问题得以圆满解决。它的优点是根基扎实,无需反复。但是,设计者面对纷繁复杂的系统,要逐个思考每一个基本简单问题的解决方法,就会陷入了一个相当复杂而尴尬盲目的境地:东一榔头西一棒子;顾了这头,忘了那头,漫无目的,耗时太多,也不理想。
2.取长补短,兼容并蓄
面向对象的设计方法落脚点是“对象”,着眼点是“面向”,因此,在教学中可以将自顶向下和自底向上的设计的优点兼而用之。比如类树的设计,自顶向下的方法是从最顶端的基类开始,一级一级派生出新类,添加新的成员,直到产生的源生类满足程序设计的要求为止。单纯使用自顶向下法,如果高层一旦要进行修改,下层的工作就会白做。这时,如果同时考虑自底向下的设计方法,情况就大为不同:在设计类树工作中,从最基层的派生类开始,提取派生类中共同的本质特征创建一个基类,这样一层一层地堆上去,最后形成合理的类族。自底向上的方法考虑的是基层的问题,大大降低了“工作到一半发现还有不可解决问题的”风险。综合运用自顶向下和自底向上两种设计方法,使建立的类树具有合理的并都能得到顺利解决的层次结构,使系统的可行性、安全性和稳定性大大增强。
二、大胆创新思维方法,提高程序的运行质量
在教学过程中,要引导学生用最简单最直接最有效的办法实现程序效率的最优化。
1.改头换面灵活运用“自由全程变量”
“自由全程”是指变量不属于任何类的成员。如Main()、标准C库的所有过程以及所有用C语言写的过程都属于“自由全程”的范畴。在C++语言产生以前,要减少或者取消自由全程的使用几乎是不可能做到的。自由全程变量的引入增强了程序设计的自由度和开放性,为广大设计者所推崇。但在实践过程中,自由全程变量的过度使用会带来很多问题,特别是对初次接触的学生来说,甚至会造成一定程度的混乱,造成很大的麻烦。灵活运用C++语言提供的相应机制可以巧妙地解决这一问题。具体分两步走:第一步,将这些全程变量的所有权划归给一些指定类的对象,并将这些全程变量确定为静态类成员,明确全程变量的使用权,把这些全程变量的管理集中在一个地方。第二步,将这些全程变量放入类中并给它取名,使全程变量和所在的类名紧紧地联系在一起。通过转换,全程变量仍然可以自由地被访问,但它的名字变成了两部分,一个是类名,一个是它本身的名字,这就杜绝了全程变量在使用过程中引起名字冲突的可能性。
2.借助内存管理系统防止“类”型的误用
在面向对象系统中,多数程序的运行行为都依赖于对象的类型。比如,一个总的表示图形形状的类,从中可以派生出各种各样特殊的图形类。在这个类族中,每个类型都必须执行各自特殊的draw()函数以便画出各自代表的图形。每次调用draw()函数时,画出的图形形状将依赖于程序实际运行时所控制的对象类型。如果制造一个陷阱谎报了类型,程序就会画出错误的图形。又比如,指向整型的指针类和指向一个具有10个整型单元的数组的指针类是完全不一样的两码事。故此,重视类型问题是有效防止错误发生的第一道防线。
借助C++语言提供的新的内存管理系统,可以使问题迎刃而解。C++语言在分配内存时,如果由于某种原因分配不成功,则返回空指针0x0000 0000。当用户继续使用比如改写数据时,系统将因为发生访问违规而退出。当然,面向对象设计方法本身,还可通过设计合理的类的层次结构,创建一组相互兼容的类型,避免发生相似的错误。
3.充分发挥“继承”在面向对象程序中的特殊功效
继承提供了很多手段。类的层次设计和实现是属于继承的面向对象设计的范畴,C++语言提供了众多的构件模块,包括公有的,保护的和私有的基类以及虚和非虚的基类,还有虚和非虚的成员函数等。用好“继承”这项工具,充分发挥“继承”在程序设计中穿针引线的特殊作用,能收到事半功倍的效果。
①把握继承的唯一性和方向性。公有继承指的“就是一个”。比如,类B公有继承于类A,就是在告诉C++编绎器类型B的每一个对象也是类型A的对象,反之则不然。如果说对于一个类型A的对象是正确的一件事,则对于一个类型B的对象同样也是真实的,反之也不行。
②尽量使用单一继承。如设计一个活动卡通人物的类属。一般来说,任何卡通人物都要跳舞或唱歌,但是每种类型的卡通人物表演这些动作的方式也是不同的。虚函数可以把所有的卡通对象的跳舞唱歌和缺省的行为动作表示成该类中的空函数。但是当要表示一个具体的卡通人物如蝴蝶或蜻蜓时,往往会陷入一些不必要的重复或继承。因为蝴蝶和蜻蜓两个类中具有很多共同的东西。并不是说让其中一个类继承于另一个类。这时不妨建立一个基类,让两个类同时继承于这个共同的基类,如定义为insect(昆虫),问题就变得简单了。
③“继承”的分层技术实现。利用分层技术“has-a(有一个)” 和“ia-implemented-in-terms-of(按·····方式实现)” 实现继承。从C++程序的执行效率来看,使用继承从base类派生一个derived类,和在derived中将base类作为它的一个对象成员是一样的。分层是一个处理过程,也可称为包含或嵌入,它通过让分层的类型包含被分层的类的对象作为其数据成员,以便把一个类建立在另一个类的上面。如:
这里,Person类被分层到String、Address和PersonNumber等几个类上面,使它继承了String、Address和PersonNumber的相关特性,因为它里面含有这些类型的数据成员,同时,又保持了Person类的相对完整。
面向对象程序设计语言的关键不在于它的语法特征,而是其所提供的对自然问题求解的机制和结构,它给用户提供的支持程序设计的窗口环境和管理工具。它是一种开放性的设计平台,要求设计者要面向实际问题,创新思维,以便更好地解决问题。
参考文献:
[1]吴炜煜.面向对象分析设计与编程[M].北京:清华大学出版社,2000.
[2]张基温.C++程序设计基础[M].北京:高等教育出版社,1996.
[3]谭浩强.C++面向对象程序设计[M].北京:清华大学出版社,2006.
[4]郑阿奇.C++面向对象实用教程[M].北京:电子工业出版社,2009.
责任编辑 赖俊辰