已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
组态软件设计中的模式研究 -图形编辑器的实现殷 飞 丁维明摘要:面向对象的软件设计能够提高软件的灵活性,可扩展性,易理解性,易维护性。在开发功能复杂,体系庞大的软件过程中,这种优势,得到更加明显的体现。在进行面向对象的软件设计过程中,设计者们不断的发现设计中总是存在一些固定的设计模式,这些模式往往来源于设计者多年的面向对象的设计经验,而且这些模式的运用解决了很多设计问题,使程序优雅而灵活,体现了面向对象编程的优越性。组态软件的设计是一项复杂的工作,因为组态软件的特性决定了它必须要求有良好的扩展性和灵活性。本文详细阐述了在组态软件的图形编辑器设计中采用的一些主要设计模式,给出了模式在本软件设计中的具体实践,提出了对模式的一些思考,分析了设计模式带来的优点。Abstract: OOP(Object-Oriented Programming) can make software flexible, extensible, understandable and maintainable. Especially when we construct complex and large applications. Designers found that some patterns always occur during the process of developing software. These patterns can solve many difficulties and make the code elegant and efficient. Most of these patterns originated from developers experience. Configuration Software for Industry is a complicated software which must be so flexible that it can be used in many various conditions. This paper mainly illustrates how to design a graphic editor a part of Configuration Software with patterns. Further detailed discussion about the patterns adopted in design was also provided.关键词:组态软件,面向对象,设计模式 随着工业自动化水平的迅速提高,计算机在工业领域的广泛应用,人们对工业自动化的要求越来越高,种类繁多的控制设备和过程监控装置在工业领域的应用,使得传统的工业控制软件已无法满足用户的各种需求。在开发传统的工业控制软件时,当工业被控对象一旦有变动,就必须修改其控制系统的源程序,导致其开发周期长;已开发成功的工控软件又由于每个控制项目的不同而使其重复使用率很低,导致它的价格非常昂贵;在修改工控软件的源程序时,倘若原来的编程人员因工作变动而离去时,则必须同其他人员或新手进行源程序的修改,因而更是相当困难。通用工业自动化组态软件的出现为解决上述实际工程问题提供了一种崭新的方法,因为它能够很好地解决传统工业控制软件存在的种种问题,使用户能根据自己的控制对象和控制目的的任意组态,完成最终的自动化控制工程。组态(Configuration)为模块化任意组合。通用组态软件主要特点有(1)延续性和可扩充性。用通用组态软件开发的应用程序,当现场(包括硬件设备或系统结构)或用户需求发生改变时,不需作很多修改而方便地完成软件的更新和升级;(2)封装性(易学易用),通用组态软件所能完成的功能都用一种方便用户使用的方法包装起来,对于用户,不需掌握太多的编程语言技术(甚至不需要编程技术),就能很好地完成一个复杂工程所要求的所有功能;(3)通用性,每个用户根据工程实际情况,利用通用组态软件提供的底层设备(PLC、智能仪表、智能模块、板卡、变频器等)的I/O Driver、开放式的数据库和画面制作工具,就能完成一个具有动画效果、实时数据处理、历史数据和曲线并存、具有多媒体功能和网络功能的工程,不受行业限制。组态软件的以上特性给软件的设计带来困难,面向对象的设计是一种比较好的选择,什么是模式,模式就是有规律的针对特定问题的解决方案,在面向对象的设计中,模式是设计者们经过多年的实践发现的有规律的对某种设计问题的解决方法。这些模式往往充分利用了面向对象编程的特性,能够高效,灵活的解决问题。设计模式概念的提出和对设计模式描述的文档化也使人们更加简单方便的复用成功的设计和体系结构。通过分析软件的需求,结合以往的设计经验,对出现的设计难点采用一定的设计模式加以解决是本文阐述的重点。关于本文的表述方式的一些说明:本文中的相关的类结构图采用了OMT(Object Modeling Technique)图来表示,因为软件的编写采用了c+作为开发语言,所以文中给出的代码是类C+的伪代码。为了方便描述,本文给出了一些模式的名称,这些名称采用了在设计模式界比较有影响的著作设计模式一文中的词汇,基本能够反映模式的特点和本质。1Composite(组合)模式:组态软件的一个重要特点是有良好的人机界面,对工业过程有直观的,动态的反映,对各种现场的实体的模拟是必需的,如对锅炉,电机,阀门等设备的图形化显示。因此,是否有一个丰富的图形编辑器是评价组态软件优劣的标准之一。通常表现一些简单的图形,如直线,矩形,圆等是比较容易的,因为这些图形的有简单的几何结构,能用简单的数学公式来描述。如何表现复杂的图形呢?我们遵循从简单到复杂的一般规律,得到这样的解决方法:复杂图形的实现可以通过组合简单图形来完成。这样可以由一些简单的几何图形组成复杂图形,这些复杂的图形还可以组合成更复杂的图形,形成一种递归的结构。从理论上而言,这种方法能够画出任意复杂的图形。如果这种方案可行,那么我们不光可以画出简单的几何图形,而且通过这些图形的组合,可以表现出复杂的工业设备,如锅炉,电机,阀门等。这样我们的设计的要求就达到了。那么,如何用面向对象的编程语言实现呢,通常可以先定义一些简单的类,这些类代表了简单图形,然后定义一个容器类来包含简单的图形类达到组合图形的目的。但是这样存在一个问题,客户的代码必须区分容器类和简单类,增加了软件的复杂度,降低了灵活性。并且,在概念上,用户常常并不区分这是一个组合图形还是简单图形,他们并不关心一个矩形,或者一个锅炉是否是组合图形,只关心怎样使用它们。如果能把组合图形当作一个简单图形一样来处理,则可以大大简化软件的设计。解决这样的问题,我们使用了Composite模式。下面给出它的类结构图图1.1上图中Graphic是一个抽象基类,他代表了图形,它是本设计中所有图形类共同的抽象接口,当然作为它的子类的Composite类也有同样的接口,这种接口上的一致性决定了,任何使用Graphic接口的地方Composite图形对象都可以使用。Add接口可以将一个图形加到组合图形中去,Remove接口则将图形从组合图形中拿出,这两个接口显然只对Composite类有意义,对简单图形没有意义,所以简单图形的Add和Remove接口什么也不做,是空操作。Composite可以用一个链表来保存它所包含的图形,Add接口就是将图形加到Composite对象的链表中去。有了这样的结构,那么Composite的Move()可以这样实现For all graphic in graphicList of Compositegraphic.move()Rotate()可以以类似的方式实现。图1.2 上图是一个通过此模式形成的递归组合图形实例,可以看出货车由矩形(货柜),圆形(车轮),和车头组成,而车头又是矩形和线条的组合图形,下图展示了这种设计模式形成的递归结构图1.3 Composite模式的精华在于组合图形和简单图形有共同接口,正因为这样,用户可以对该货车图形像简单图形般操作,移动,缩放,旋转,甚至与其他图形再组合形成更复杂的图形。组合模式的引入极大的简化了编程,增加了灵活性。从很多应用来看,这种模式应用的很广,许多著名的面向对象的应用框架中几乎都采用了此模式,如Unidraw,InterView等2Prototype(原形)模式试想图形编辑时,如果一个复杂的图形需要用两次,用户不可能再重画一遍该图形,众所周知的方法是为用户提供图形复制的功能。其中一种方法这样实现,首先确定被复制图形的类型,然后新建一个这种类型的对象实例,最后将被复制的对象赋给新对象达到复制的目的。这种方法有两个主要缺点,首先需要判断对象的类型,这本身不符合面向对象的设计原则,再者,在存在复杂组合图形的情况下,这种方法实现起来比较困难。因此,引入了Prototype模式,在这种模式下,图形的复制功能交给对象本身,即无需判断对象的类型,直接调用对象的接口返回一个复制好的对象,因为对象总是知道自己是什么类型,自身包含那些信息,它能准确无误地复制自己。Prototype模式的关键是为所有图形对象实现了一个Clone(克隆)接口(参见图1. 1),每一个对象可以克隆其自身,这样就将复制的功能封装在对象中,简化了使用对象的客户代码。对组合图形的复制可以通过递归的方法实现。伪代码如下:Graphic *Composite:Clone()Graphic *p = new Composite;forall graphic in graphicListp-Add(graphic-clone()return p;Composite的Add操作可参考Composite模式。使用Prototype还能实现一些其他重要的功能,如图形库的使用。在工业生产中有很多设备,这些设备的形状大都是标准的,因此我们可以事先用编辑器做好一系列的图形库,需要时无需客户自己画,而是直接从库中引入,极大的方便了开发。实现时只需让图形库中的图形克隆一个自身的对象便能实现库中图形的引入。3State(状态)模式允许一个对象在其内部状态改变时改变它的行为。考虑图形编辑时,客户选择不同的编辑工具时,则能实现不同的功能,如选择圆形作图工具时,鼠标左键在编辑区按下,拖动,松开一系列的动作后,画出一个圆形。若选择的是旋转工具,则上述一系列动作是使一个选中的图形旋转一定的角度,若选择的是线条工具,则画出一条直线。如何反映出这种行为的变化,是值得考虑的问题,一个显而易见的方法是可以用一个变量(一般是个整数值)表示当前编辑器的状态,然后根据当前状态值,作出不同行为,伪代码看起来像这样If (state = ROTATE) /*旋转*/ Rotate(graphic)if (state = CIRCLE) /*画圆*/ DrawCircle()if (state = LINE) /*画线*/ DrawLine()类似这样的代码可能会充斥在不同的鼠标响应函数里,这种方法能够符合要求,似乎也合情合理。但是当工具比较多时,就会出现不受欢迎的巨大的条件语句块,而且这种看起来差不多的语句块会出现在多个函数体内,这种现象的使我们觉得代码产生重复,这种不合理性导致我们考虑采用新的代码组织方式。进一步考虑,如果你需要增加新工具,问题出现了,你不得不添加一个状态值,然后在每个响应函数里添加一个条件选择语句。面向对象设计的一个重要理念就是封装变化,既然状态是变化的,那我们可以考虑将状态封装。这种情况下我们想到了使用State(状态)模式。该模式类结构图如下:图3.1 编辑器中存储一个指向tool(工具)的指针,用户的所有相关操作都转发给tool(工具)处理,不同的tool对象封装了不同的功能,运行时可以动态的切换编辑器中的tool指针所指向的tool对象,这样状态值的变化变成了状态对象的变化。该模式的使用,消除了原本需要的大量条件语句,条件语句判断由编辑器中tool指针所指对象的切换所代替。而且易于增加新的工具,只需要写一个新的tool类,并在需要时装配到编辑器上去,就可以实现新的功能。事实上,一个包含许多条件语句的代码通常意味着可能需要用state模式。至于怎样进行状态转换,一种方法可让编辑器指定转换,一种方法让状态对象本身来决定后继状态。但是显然,本设计中让编辑器指定状态转换更为合理,因为各个tool对象之间并没有依赖关系,tool对象的切换由用户的选择决定。由于tool对象特殊性,它的实现可以参照下一节中的Singleton模式。4Singleton(单件)模式:有时,我们在应用中只需要一个对象实例,但是怎样才能保证只有一个对象实例呢,用全局变量似乎可以达到这个目的,但是全局变量不但pollute(污染)了名空间,容易造成名称冲突,而且当多个客户使用你的类时,他们很可能会自己重新创建一个对象实例,因而无法保证只有一个对象实例。全局变量还有一个小缺点就是不管你是否用到了该实例变量,该变量实例从程序开始运行直到退出将一直存在。Singleton模式很好的解决了这些问题。在图像编辑器的实现中,有一个类叫GraphicFactory(图像工厂),他负责根据类名生成相应的图形对象,该接口形如Graphic *CreateGraphic(string className),在这个应用中,仅需要存在一个GraphicFactory实例变量,存在多个图像工厂对象是没有什么意义的。因此采用了Singleton模式。下面给出简化后的C+代码Class GraphicFactorypublic:static GraphicFactory *Instance();Graphic *CreateGraphic(string *className)protected:GraphicFactory(); Private:Static GraphicFactory *m_insance;GraphicFactory * GraphicFactory:m_insance = 0;GraphicFactory * GraphicFactory :Instance()if (m_instance = 0)return new GraphicFactory;elsereturn m_instance;Graphic *GraphicFactory:CreateGraphic(string *className)if (className = “LINE”)return new Line;else if (className = “RECT”)return new Rect;elsereturn 0;这个模式比较有意思的是,图形工厂负责保存自身的一个实例。因为这个变量是静态私有成员变量,这保证了其他对象不能直接访问它。客户仅需要使用GraphicFactory:Instance()-CreateGraphic(className)就可以创建一个需要的图形对象。另外Instance接口的内部实现使用了lazy( 惰性)初始化,当第一次使用时,才创建对象。进一步,如果对内存的使用比较在意的话,可以实现一个Free接口,这个接口负责释放这个对象,当使用完GraphicFactory后用GraphicFactory:Free()立即释放它。Free()接口的实现代码类似于这样void GraphicFactory :Free()if (m_instance != 0)delete m_instance;m_instance = 0;这种做法节约了运行时的内存开销,但是减慢了运行的速度,因为创建和释放对象都需要一定的时间开销。需不需要Free接口,可根据情况具体分析。本设计中未采用Free接口,因为编辑器需要GraphicFactory频繁的创建对象,而且GraphicFactory对象本身没什么状态,所需的内存很小,用完后即释放的意义不大。顺便提一下,类的(constructor)构造器声明为保护型的,当客户试图在其他地方实例化该类时,会
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025湖南怀化市中方县紫荆学校公益性岗位招聘1人考试笔试备考题库及答案解析
- 2025福建厦门市集美区杏东小学非在编教师招聘1人笔试考试参考试题及答案解析
- 2025重庆市铜梁区华兴镇人民政府公益性岗位招聘1人考试笔试参考题库附答案解析
- 2025年新巴尔虎右旗委党校引进急需紧缺专职教师工作人模拟试卷及答案详解名师
- 2025年全国高校辅导员素质能力大赛考试测试题附参考答案(共三套)
- 医院医患关系改善措施
- 河北深州市长江中学2026届化学高三上期末教学质量检测模拟试题含解析
- 新疆库尔勒市新疆兵团第二师华山中学2026届高三化学第一学期期末联考模拟试题含解析
- 综合应用能力事业单位考试试题与参考答案(2025年)
- 2025年普法宣传知识竞赛考试题库及答案(超强)
- 2025年江苏紫金财产保险股份有限公司招聘笔试参考题库含答案解析
- CNAS-CL02-A004:2018 医学实验室质量和能力认可准则在临床免疫学检验领域的应用说明
- 幼儿园一日活动观摩
- 游戏开发者入门作业指导书
- 合同签订培训课件
- 诊疗技术规范与医疗操作规程
- 2025年中银金融租赁有限公司招聘笔试参考题库含答案解析
- 人教版七年级上册历史全册思维导图
- 2023-2024学年高一上学期期中化学试题及答案
- 西师版五年级上册(全册)数学【知识点详细梳理】
- 浙江省浙南名校联盟2024-2025学年高二上学期期中联考 化学试题
评论
0/150
提交评论