1、定义:
将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
2、结构图:
3、协作角色:
Command 声明执行操作的接口。
ConcreteCommand 将一个对象绑定与一个动作,调用接受者相关的操作,以实现Execute()
Client 创建一个具体的对象并设定它的接收者
Invoker 要求该命令执行这个请求,
Receiver知道如何实施与一个请求相关的操作,任何类都可能成为一个接收者
4、适用性:
对象可抽象出待执行的动作以参数化别的对象。
在不同时刻指定、排列和执行请求。
支持取消操作。
支持修改日志
用构建在原语操作上的高层操作构造一个系统
5、实现:
1、需求:uboot上其命令按照一定的格式封装成一个对象,供客户在控制台通过输入命令调用。
2、实现(模拟uboot命令):
command.h
#ifndef __COMMAND_H__
#define __COMMAND_H__
struct cmd_tbl_s {
char *name;
int maxargs;
int repeatable;
int (*cmd)(struct cmd_tbl_s *, int , int ,char *[]);
char *usage;
char *help;
};
typedef struct cmd_tbl_s cmd_tbl_t;
int cmd_init();
int command_add(cmd_tbl_t *cmdtp);
int cmd_del(cmd_tbl_t *cmdtp);
int cmd_find_item(cmd_tbl_t **cmdtp,char *name);
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name = {#name, maxargs, rep, cmd, usage, help}
#define CONFIG_SYS_MAXARGS 16
#define cmd_usage(cmdtp,st) \
do { \
printf("%s--%s\n",((st *)cmdtp)->name,((st *)cmdtp)->usage); \
if(!((st *)cmdtp)->help) \
{ \
printf("no help\n"); \
return 1; \
} \
printf("%s \n",((st *)cmdtp)->help); \
return 0; \
}while(0)
#endif
cmd_nand.c
#include <stdio.h>
#include <string.h>
#include "command.h"
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
char *cmd;
printf("%s %d\n",__func__, __LINE__);
if(argc < 2)
goto usage;
cmd = argv[1];
if(strcmp(cmd, "info") == 0)
{
printf("\nprint nand %s\n",cmd);
return 0;
}
else if((strncmp(cmd, "read",4) == 0)|| (strncmp(cmd, "write", 5) == 0))
{
printf("\nnand %s\n",cmd);
return 0;
}
else
{
printf("\nnand %s\n",cmd);
}
usage:
printf("cmdtp %p\n",cmdtp);
cmd_usage(cmdtp,cmd_tbl_t);
}
U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
"NAND sub-system",
"info - show available NAND devices\n"
"nand read - addr off|partition size\n"
"nand write - addr off|partition size\n"
" read/write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
);
void register_nand()
{
command_add(&__u_boot_cmd_nand);
}
cmd_env.c
#include <stdio.h>
#include "command.h"
char env[256] = "cmd env test\n";
int do_env(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
char *cmd = NULL;
if(argc < 2)
goto usage;
cmd = argv[1];
if(strcmp(cmd, "show") == 0)
{
printf("\nENV is :\n %s\n",env);
return 0;
}
else if(strcmp(cmd, "store") == 0)
{
if(argc < 3)
goto usage;
sprintf(env,"%s",argv[2]);
return 0;
}
usage:
cmd_usage(cmdtp,cmd_tbl_t);
}
U_BOOT_CMD(env,CONFIG_SYS_MAXARGS,1,do_env,
"ENV sub-system",
"print env - env show\n"
"env store [string]-env store\n");
void register_env()
{
command_add(&__u_boot_cmd_env);
}
cmd.c
#include <stdio.h>
#include <string.h>
#include "command.h"
#define CMD_NUM 10
struct cmd
{
cmd_tbl_t *command;
int flag;
};
struct cmd command[CMD_NUM];
int cmd_init()
{
memset(command,0, sizeof(command));
register_nand();
register_env();
}
int command_add(cmd_tbl_t *cmdtp)
{
unsigned int i;
if(NULL == cmdtp)
return 1;
for(i = 0; i < CMD_NUM; i++)
{
if(command[i].flag == 1)
continue;
else
break;
}
if(i == CMD_NUM)
{
printf("command is full");
return 1;
}
command[i].command = cmdtp;
command[i].flag = 1;
return 0;
}
int cmd_del(cmd_tbl_t *cmdtp)
{
unsigned int i;
if(NULL == cmdtp)
return 1;
for(i = 0; i < CMD_NUM; i++)
{
if(command[i].flag == 1)
{
if(strcmp(command[i].command->name, cmdtp->name) == 0)
{
memset(&command[i], 0, sizeof(struct cmd));
return 0;
}
}
}
return 1;
}
int cmd_find_item(cmd_tbl_t **cmdtp,char *name)
{
unsigned int i;
if(NULL == cmdtp)
return 1;
for(i = 0; i < CMD_NUM; i++)
{
if(command[i].flag == 1)
{
if(strcmp(command[i].command->name, name) == 0)
{
printf("%s %d cmdtp.cmd %p\n",__func__, __LINE__,command[i].command->cmd);
*cmdtp = command[i].command;
return 0;
}
}
}
return 1;
}
client.c
#include <stdio.h>
#include <string.h>
#include "command.h"
int check_cmd(char *cmd)
{
unsigned int len;
unsigned int i;
len = strlen(cmd);
for(i = 0; i < len - 1; i++)
{
if((cmd[i] >= 'a')&&(cmd[i] <= 'z'))
continue;
else
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
cmd_tbl_t *cmdtp = NULL;
char *cmd;
if(argc < 3)
{
return 1;
}
cmd = argv[1];
if(check_cmd(cmd))
return 2;
cmd_init();
if(cmd_find_item(&cmdtp,cmd))
return 3;
printf("%s %d cmdtp.cmd %p\n",__func__, __LINE__,cmdtp->cmd);
cmdtp->cmd(cmdtp, 0, argc - 1,&argv[1]);
return 0;
}