lonelyrains的专栏

最近在弄一个公司的设备管理框架,发现可以把设备抽象出来,对其他可能的设备也可能用这一套框架。出于保密原则,删除了公司业务相关的信息,就列出来如下。

DevTool模块1程序描述DevManager简称DM,ViewManager简称VM。程序启动后,DevManager内注册对Controller的事件处理回调eventCallbackForDM,以便Dev事件到来时回调;ViewManager内注册对Controller的事件处理回调eventCallbackForVM,以便UI事件到来时回调。eventCallbackForDM内调用dispatchRequestFromCfg解析是否有匹配的事件对应的需求需要处理,如果有而且需要界面,则调用getDataFromDMtoVMForView从DevManager中获取对应界面需要的相应数据,并调用ViewManager的回调requestCallback处理对应的UI请求,最终弹出UI。UI处理完之后,调用eventCallbackForVM,通知Controller对应UI的完成事件,并将UI的返回数据保存在Controller内,然后Controller内调用getDataFromVMtoDMForDev组织数据,调用DevManager的requestCallback请求,最终调用DevApi更新Dev内数据。如果需要提示操作结果,还需要经历一次DM-Controller->VM->Controller的操作。上述描述是针对Dev事件处理的,也有来源于用户操作的处理。如果是类似修改名称的操作,处理顺序为VM->Controller->DM->Controller->VM-> Controller。1)VM先启动主页面,响应用户按钮请求,修改名称是在VM内弹框;2)填完Dev名称,合法验证通过后,Controller获取数据形成Dev的Request;3)DM内调用封装好的DevApi实现修改名称,成功之后,返回给Controller;4)Controller发送UI的Request,说明修改名称成功;5)VM弹出修改成功提示,用户点击成功;6)VM通知Controller确认成功。在5)用户点击成功之前,如果此时用户断开Dev,而且用户需求中要求断开Dev之后关闭相关的对话框,将从DM->Controller->VM完成一次关闭提示框的操作。在DM和VM之间加一层Controller的好处是所有需要配置定制的部分全部在此部分完成,其他实现可以以库的形式提供。抽象一层Controller,还有一个好处,是不用在VM内缓存任何数据。比如想实现一个下拉框选择Dev,仅仅有连接/断开事件时传Dev指针到VM内是不够的,需要VM自己维护已有的Dev列表。UML静态图如下:

2功能DevManager、ViewManager 分别实现设备管理、视图管理。主程序内实现控制器的功能,连接各个模块,实现消息的传递、客户定制需求的处理。2.1设备管理连接Dev则新建Dev对象存入devMap,所有针对Dev的数据操作都由DevManager进行。除了与Dev通信,还要负责回复Controller的请求数据、调用Controller的回调,通知Controller事件来了。2.2视图管理响应Conroller的请求弹出UI,当UI操作结束时,调用Controller的回调返回UI操作的结果。2.3控制器Conroller提供回调函数给DevManager、ViewManager,以响应事件,并实现对配置的解析,针对当时的事件,生成相应的请求,提交给DevManager和ViewManager。2.4性能2.5输入项2.6输出项无。2.7算法无。2.8流程逻辑无。2.9接口数据传输统一采用XML格式,如果某些元素是二进制流数据,且不是无符号整型,也先转成十六进制字符串,然后再传输。2.9.1ViewType定义格式支持的视图类型:View、ListView、TabView、ImageView、Button、ComboBox、TextView、TableView、TrayView、BubbleView、AnimateView。支持的视图内容布局类型:contentLayout(left/right/center/top/down) marginWidth/marginHeight支持的布局类型:linearLayout(vertical/horizontal)支持的宽高类型:height/width(30%/30) %方式定义与父窗口的相对位置,纯数字定义与MFC的rc文件中定义单位相同例如定义一个竖型的管理工具mainView<?xml version="1.0" encoding="utf-8"?><view><viewType>mainView</viewType><width>500</width><height>400</height><IsCenterToDeskTop>true<isCenterToDeskTop><linearLayout orientation = "vertical"><linearName>outline</linearName><marginWidth>2%</marginWidth><width>96%</width><height>96%</height><!–headline–><linearLayout orientation = "horizontal"><linearName>headline</linearName><marginWidth>2%</marginWidth><width>96%</width><height>5%</height><backgroundColor>#0001</backgroundColor><imageView><imageName>logoIco</imageName><imageUrl>$(res)/logoIco.png</imageUrl><contentLayout>center</contentLayout><marginWidth>2%</marginWidth><width>5%</width><height>96%</height></imageView><textView><marginWidth>2%</marginWidth><width>70%</width><height>96%</height><textValue>$(CustomerName)$(DevName)$(ToolName)</textValue></textView><button><id>btn_min</id><action>onMin</action><marginWidth>2%</marginWidth><width>5%</width><height>96%</height><imageUrl>$(res)/btn_min.png</imageUrl></button><button><id>btn_max</id><action>onMax</action><marginWidth>2%</marginWidth><width>5%</width><height>96%</height><imageUrl>$(res)/btn_max.png</imageUrl><isEnable>false</isEnable></button><button><id>btn_close</id><action>onClose</action><marginWidth>2%</marginWidth><width>5%</width><height>96%</height><imageUrl>$(res)/btn_close.png</imageUrl></button></linearLayout><!–logo long–><imageView><imageName>logoLong</imageName><imageUrl>$(res)/logoLong.png</imageUrl><contentLayout>center</contentLayout><marginWidth>2%</marginWidth><width>96%</width><height>30%</height></imageView><textView><marginWidth>2%</marginWidth><width>70%</width><height>50%</height><textValue>$(CustomerName)$(DevName)$(ToolName)</textValue></textView><linearLayout orientation = "horizontal"><linearName>headline</linearName><marginWidth>2%</marginWidth><width>96%</width><height>56%</height><!–logo–><listView><id>listView_mainView</id></listView><!–btnlist–><linearLayout orientation = "vertical"><linearName>btnList</linearName><marginWidth>2%</marginWidth><width>36%</width><height>56%</height><button><id>btn_change_name</id><action>onChangeName</action><marginWidth>2%</marginWidth><width>96%</width><height>10%</height><isEnable>false</isEnable></button><button><id>btn_view_devinfo</id><action>onView devinfo </action><marginWidth>2%</marginWidth><width>96%</width><height>10%</height><isEnable>false</isEnable></button><button><id>btn_init</id><action>onInit</action><marginWidth>2%</marginWidth><width>96%</width><height>10%</height><isEnable>false</isEnable></button></linearLayout></linearLayout></linearLayout></view>2.9.2DM->Controller交互事件数据格式<?xml version='1.0' encoding='utf-8'?><event><eventType>connect</eventType><devIndex>3</devIndex></event>eventType可选择connect/disconnect/format/datachange在Controller的eventCallbackForDM中调用。然后Controller调用getDatatFromDMtoVMForView,组织下一小节中描述的Controller->VM交互请求数据。mapToUIId标签实现从数据到UI填充的映射。2.9.3Controller->VM交互请求数据格式<?xml version='1.0' encoding='utf-8'?><request><requestType>createUI</requestType><view><viewType>mainView</viewType><viewId>view_1</viewId><viewParentId>desktop</viewParentId><devList><!—此处的id与viewType定义中的控件对应的id相同,表示填充到对应的id里–><id>devList</id><mapToUIId>listView_mainView</mapToUIId><selectedId>dev_1</selectedId><dev><id>dev_1</id><name>DevStd</name><sn>DS20150415</sn><imageUrl>$(res)/dev.png</imageUrl><otherParamList><param1><id>param_1</id><imageUrl>$(res)/param1.png</imageUrl></param1><param2><id>param_2</id><imageUrl>$(res)/param2.png</imageUrl></param2></otherParamList ></dev></devList><button><id>btn_change_name</id><isEnable>true</isEnable></button><button><id>btn_view_devinfo</id><isEnable>true</isEnable></button><button><id>btn_init</id><isEnable>true</isEnable></button></view></request>requestType可以是一些已在概要设计里归纳需要实现的需求,比如createUI、closeUI、showUI、hideUI、updateUI。updateUI中对应的是viewId。当且仅当是createUI需要viewType、viewParent、devId。createUI的返回参数有一个是viewId。该数据格式在VM的requestCallback中调用。2.9.4VM->Controller交互事件数据格式<?xml version='1.0' encoding='utf-8'?><request><requestType>updateUI</requestType><view><viewType>mainView</viewType><viewIndex>view_1</viewIndex ><event>click</event ><listView><id>listView_mainView</id><selectedId>param_2</selectedId></listView></view></request>用户点击了listView的证书节点。该数据格式在DM的eventCallbackForVM中调用。用户选择了证书,则提交请求使能证书操作相关按钮。Controller->VM的请求在VM的requestCallback中调用,格式如下:<?xml version='1.0' encoding='utf-8'?><request><requestType>updateUI</requestType><view><viewId>1</viewId><viewType>mainView</viewType><button><id>btn_view_param2</id><isEnable>true</isEnable></button></view></request>用户点击了修改名称按钮。则调用一次VM->Controller的交互事件,声明按钮动作,Controller再提交一次到VM的交互请求:<?xml version='1.0' encoding='utf-8'?><request><requestType>createUI</requestType><view><viewType>changeLabelView</viewType><viewId>view_2</viewId><devList><dev><name>dev1</name><id>dev1_devStd</id><value>devStd</value><mapToUIId>oldName</mapToUIId></label><sn><id>DS20150415<id><mapToUIId>sn</mapToUIId></sn></dev></devList></view></request>用户点击了changeNameView的OK之后,调用一次VM->Controller的交互事件,正式调用修改名称操作。2.9.5Controller->DM的交互请求数据格式<?xml version='1.0' encoding='utf-8'?><request><requestType>updateDev</requestType><dev><id>dev1_devStd</id></dev><action>changeName</action><paramList><oldName>devStd</oldName><newName>devStdNew</newName></paramList></request>该消息在DM的requestCallback中调用。requestCallback处理完之后,如果执行成功,Controller再发一次到VM的更新消息,改变UI显示的Name,并创建一个提示框,提示成功。3补充说明:1、同步异步调用的实现区别:同步:调用者会等待回调结束之后做下一步操作。异步:调用者请求之后,马上返回。如果有更新的结果,则以事件方式通知Controller。完全不需要在调用者和被调用者创建新的线程来检测。这样做的要求是要在同一进程里。如果非得是不同进程,可以考虑实现一种RPC远程过程回调。但是目前来看,从之前讨论过的安全性问题来看,应该尽量做到同一进程,然后UI以库形式调用。2、UI中定义的按钮响应函数处理方法:所有的按钮功能在Controller中定义,比如修改名称,按照字符串匹配查找相应的函数指针,并填充相应的参数列表。可以统一所有的参数均为字符串。3、UI中的隐藏:通过Width或者Height更新为0%即可。至此,可以统一所有的UI请求,,不论是不是管理工具发出的,或者即使是安装包的UI,都可以按照这一套来做,完全解耦。全部用XML定义。

我走得很慢!但我从不后退!

lonelyrains的专栏

相关文章:

你感兴趣的文章:

标签云: