做网站和app多少费用,苏州市工业园区规划建设局网站,东莞建设局门户网站,wordpress flash加载插件深入浅出设计模式--命令模式 一、背景二、问题三、解决方案四、试用场景总结五、后记 一、背景 命令模式是一种行为设计模式#xff0c;它可以将用户的命令请求转化为一个包含有相关参数信息的对象#xff0c;命令的发送者不需要知道接收者是如何处理这条命令#xff0c;多个… 深入浅出设计模式--命令模式 一、背景二、问题三、解决方案四、试用场景总结五、后记 一、背景 命令模式是一种行为设计模式它可以将用户的命令请求转化为一个包含有相关参数信息的对象命令的发送者不需要知道接收者是如何处理这条命令多个功能入口可以发送同一命令避免多处多次实现相同功能的冗余代码。另外可以对命令进行延迟处理或放入队列或栈中支持命令回撤。
二、问题 在使用GUI界面的应用程序时一般保存功能会有多个入口比如点击按钮保存、点击菜单项保存和使用键盘ctrls保存等每个入口的位置不同且没有什么关联关系只是最终实现文档保存功能的代码是一样的。 此时要么将这些操作代码复制粘贴进多个类中要么就是让菜单项依赖于按钮显然这两种方式都是不明智的。
三、解决方案 一般在这种一对多、多对多的场景下最好的方式是添加一个中间层上层负责GUI的交互下层负责业务逻辑的处理中间层则将命令请求抽象为一个对象在上下两层中传递消息数据该对象可以连接不同的GUI和业务逻辑对象GUI 对象无需了解业务逻辑对象是否获得了请求也无需了解其对请求进行处理的方式。 1. 该模式的类图如下所示发送者ICommandSender中包含了命令接口ICommand的指针ICommand中只有execute虚函数具体的命令类SaveCommand中包含有命令接收者Document的指针且重写execute函数。CommandHistory类记录了每条执行了的命令调用pop弹出命令时可以调用该命令的redo函数下图中未展示进行命令撤销。 2. 该模式下各类之间交互的时序图如下首先生成命令接收者Document然后生成命令SaveCommand并绑定Document接下来生成命令发送者Button并绑定SaveCommand最后Button调用触发函数click让命令对象去执行具体的execute函数。 3. 相关代码实现
命令发送者
class CommandHistory{
public:static CommandHistory* GetInstance(){static CommandHistory cmdHis;return cmdHis;}void push(ICommand* cmd){m_cmdHisVec.push(cmd);}void pop(){m_cmdHisVec.pop();}size_t size(){return m_cmdHisVec.size();}
private:stackICommand* m_cmdHisVec;
};#define CMD_HIS CommandHistory::GetInstance()class ICommandSender{
public:ICommandSender(){}~ICommandSender(){}void setCommand(ICommand* cmd){m_cmd cmd;}ICommand* getCommand(){return m_cmd;}
protected:ICommand* m_cmd;
};class Button : public ICommandSender{
public:void click(){m_cmd-execute(Sent by Button);CMD_HIS-push(m_cmd);cout Count of Button history command is CMD_HIS-size() endl;}
};class Shortcut : public ICommandSender{
public:void setCommand(const string key, ICommand* cmd){m_cmd cmd;m_keyCmdMap[key] cmd;}void press(){m_cmd-execute(Sent by Shortcut);CMD_HIS-push(m_cmd);cout Count of Shortcut history command is CMD_HIS-size() endl;}
private:mapstring, ICommand* m_keyCmdMap;
};命令
class ICommand{
public:virtual ~ICommand(){}virtual void execute(const string from) 0;
};
class SaveCommand : public ICommand{
public:SaveCommand(Document* doc) : m_doc(doc) {}virtual void execute(const string from) override{m_doc-setText(from);m_doc-save();}
private:Document* m_doc;
};命令接收者
class Document{
public:void setText(const string text){m_text text;}void save(){cout m_text has been saved endl; }
private:string m_text;
};四、试用场景总结
若多个不同操作对应同一处理结果那么可以使用命令模式。如点击菜单项、点击按钮和ctrls进行保存若同一操作在不同的场景下产生不同的结果在运行时切换已连接的命令也可以使用命令模式。如用户可以配置菜单项在点击时触发不同的命令。若需要将操作放入队列中延迟或计划发送命令也可以使用命令模式。若要实现操作回滚撤销功能也可以使用命令模式。命令历史记录是一种包含所有已执行命令对象及其相关程序状态备份的栈结构。若要远程执行命令需要将命令对象序列化从而能方便地写入文件或数据库中。
五、后记
以上所有内容均为原创代码已上传至gayhub https://github.com/gangster-puppy/Design-Pattern.git