分享
 
 
 

一个Command模式的应用例子

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

我曾经写过一个小软件,故事是这样的:我们公司有一些设备在外面运行,有一天我接到一个任务,要求我编写一个算法对系统进行控制,改善系统的性能。根据大家的讨论很快制订了算法,我也很快编码完毕。但问题来了,我怎样进行测试,怎样验证这个算法呢?我可以在家里进行仿真,模拟系统的真实运行情况,但仿真终归仿真,我对算法是否真正有效心里没底;我更加不可能拿到外面测试,那可是商用系统,万一出了纰漏我可担当不起。



经过冥思苦想后(有一点夸张,呵呵),终于被我想出了一个办法。系统具有一样功能,可以由人机命令设置来进行数据采集,可以在运行期间产生运行记录存放在一个日志文件中,每一条运行记录对应着系统的一次执行状况,也对应着日志文件中的一行,具有固定的格式。在一个小时内,大约可以产生几千条这样的记录。



我要求系统维护人员在若干个典型时段进行采集,最后交到我手里就是几个日志文件,分别代表不同的时段系统运行的状况。假如我能够从这些日志文件中”还原“出系统的真实运行轨迹的话,那么我就可以有效的验证我们的算法。



我题目已经说了,这是一个运用Command模式的例子,因此我首先简单介绍一下Command模式。按照GoF的定义,Command模式的意图就是将一个请求封装为一个对象,从而你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,支持可撤销的操作。



Command模式的好处是可以将调用者和命令执行者解耦,有时候命令调用者并不知道命令要如何执行,例如你点击一个菜单项,但真正的执行是由应用程序决定。因此通过事先注册好的命令,利用多态技术,命令调用者即使不知道具体命令的类型也可以执行它(所有命令都提供一个Execute()的虚拟接口)。具体的Command对象是一个智能的对象,它知道相关的Context,所以它知道如何去执行具体的操作。



对我来说,我在这个项目中运用Command模式是想利用Command模式的另外一个优点,就是万一系统崩溃了,也可以通过已经备份日志来重新执行这些命令,从而重新”还原“整个系统。

现在我就有这些日志,我的目标就是通过它们来重新模拟整个系统的运行轨迹。



我的做法大致是这样的:

首先定义一个Command的抽象基类

struct Command {

 unsigned int timestamp;

 //other property

 virtual void execute () = 0;

 virtual ~Command() {}

};



然后定义3种不同类型的具体Command类

struct SuccessCommand : public Command {

 void execute ()

 {

 //do something...



 }

};



struct FailureCommand : public Command {

 void execute ()

 {

 //do something...



 }

};



struct TimerCommand : public Command {

 void execute ()

 {

 //do something...



 }

};



最后我定义一个std::vector< Command * >来存放这些Command的指针。

具体做法是从日志文件中读取满足特定条件的记录,比如说,某个小时内的所有记录。然后判断它们的状态是成功还是失败,来生成不同的命令。

std::vector< Command * > comvec;

if (GetSysStatus(str) == SUCC)

{

 comvec.push_back(new SuccessCommand);

}

else

{

 comvec.push_back(new FailureCommand);

}



处理完毕后,因为我的算法是把1小时平均等分成若干个时间段,在时间段边界(例如每1分钟,可灵活设置)开始启动算法进行控制,所以我生成了若干个TimerCommand,添加到comvec中。

//byPeriod为算法启动间隔,byHour为指定小时

for (int i=byPeriod ; i<60; i+=byPeriod )

{

pCommand = new TimerCommand();

pCommand->timestamp = byHour * 3600 * 1000 + i * 60 * 1000;

//other processing

comvec.push_back (pCommand);

}

由于每个Command都有一个timestamp时间戳字段,因此我可以根据timestamp来进行排序,这个很简单:

sort (comvec.begin(), comvec.end(), LessTimeStamp);



LessTimeStamp是我自定义的一个比较函数,根据时间戳排序

bool LessTimeStamp (const Command *com1, const Command *com2)

{

 return com1->timestamp < com2->timestamp;

}



排完序后,一个符合我要求的Command序列就诞生了!现在我既得到了系统的真实运行轨迹,同时又把我的算法控制点插入其中,这样得到的仿真结果就是真实可信的。



vector< Command * >::iterator end = comvec.end();

for (vector< Command * >::iterator it = comvec.begin(); it != end; ++it)

{

 (*it)->execute();

}



Command模式是强大的,我的体会是要学习它的精髓,但不必太拘泥于它的实现形式,对其他模式也一样。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有